Tewr / BlazorWorker

Library for creating DotNet Web Worker threads/multithreading in Client side Blazor
MIT License
392 stars 36 forks source link

BlazorWorkerJSRuntime JS to .NET Interop #105

Closed graham83 closed 8 months ago

graham83 commented 8 months ago

Its fantastic that we can call JS from the worker, however having issues calling .NET from JS within BlazorWorker context. Should JS Interop from JS -> .NET work in a BlazorWorker?

Can see BlazorWorkerJSRuntime.InvokeMethod has [JSExport] and can see in the call hierarchy so looks like it is intended to work as part of the JSRuntime extension but cannot see any examples. Only .NET -> JS

My implementation: BlazorWorker service SubscriptionService:

private BlazorWorkerJSRuntime _jsRuntime;
..

public SubscriptionService(IJSRuntime jsRuntime, ...)
        {
                _jsRuntime = (BlazorWorkerJSRuntime)jsRuntime;
        }`
        ..
          public async Task NewSubscriptionRequest(..)
        {
         ..
          var dotNetObjectReference = DotNetObjectReference.Create(this);
          await _jsRuntime.InvokeVoidAsync("createSubscription", dotNetObjectReference);
          ..
         }

        [JSInvokable]
        public static void CallbackHandler()
        {
            Console.WriteLine("Callback from worker script");
        }

Imported script using JSInvokeService.ImportLocalScripts

javascript:

self.createSubscription = (dotnetHelper) => {
    console.log(`JS interop from BlazorWorker called`);
    dotnetHelper.invokeMethodAsync('CallbackHandler');
}

We see JS interop from BlazorWorker called in the console so I know the .NET -> JS interop working. In 4.00 was getting exception in the callback to CallbackHandler. In 4.1.2 it fails silently.

4.00 exception:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'serialize')
    at BlazorWorkerJSRuntime.js:11:52
    at new Promise (<anonymous>)
    at DotNetObjectProxy.invokeMethodAsync (BlazorWorkerJSRuntime.js:9:16)
    at self.createSubscription (dxfeed.js:44:18)
    at Object.workerInvokeAsync [as WorkerInvokeAsync] (BlazorWorkerJSRuntime.js:73:26)
    at invoke-js.ts:201:31
    at Ul (invoke-js.ts:276:5)
    at dotnet.native.wasm:0x1faef
    at dotnet.native.wasm:0x1bf8c
    at dotnet.native.wasm:0xf173

Thanks for any assistance.

graham83 commented 8 months ago

image

Seems like const serializer = new BlazorWorkerJSRuntimeSerializer(); is not recognized in the constructor here.

Getting the exception on 4.1.2 again.

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'serialize')
    at BlazorWorkerJSRuntime.js:11:52
    at new Promise (<anonymous>)
    at DotNetObjectProxy.invokeMethodAsync (BlazorWorkerJSRuntime.js:9:16)
    at self.createSubscription (dxfeed.js:44:18)
    at Object.workerInvokeAsync [as WorkerInvokeAsync] (BlazorWorkerJSRuntime.js:73:26)
    at invoke-js.ts:201:31
    at Ul (invoke-js.ts:276:5)
    at dotnet.native.wasm:0x1faef
    at dotnet.native.wasm:0x1bf8c
    at dotnet.native.wasm:0xf173
Tewr commented 8 months ago

Should JS Interop from JS -> .NET work in a BlazorWorker?

Yes I'm pretty sure this should work.

I think this is a bug introduced when migrating to net8. Also, I can't find the test. Probably means its not covered by a test anymore. I'll try to find to time to debug this week

Tewr commented 8 months ago

To call static methods, line 7 and 8 in the example from my pr should work already in current version. However calling instance methods with DotNetObjectReference was completely broken, but I'm confident this PR will fix it. I'll see if I have the time to test this a tad more and create a release next week. In your example code you mixed up the concepts a bit as you are trying to call a static method using a DotNetObjectReference

graham83 commented 8 months ago

Thanks! Tested today with the DotNetObjectReference method fix in your PR and is working now. Seems like my example was leftover code after trying to refactor to JSExport, thanks for correcting! Will defo use the next release when you merge. Also kudos for the JSDirect implementation, as will replace a bunch of chained calls my code to hit the main js! Top work!

Tewr commented 8 months ago

This has been released.