LostBeard / SpawnDev.BlazorJS

Full Blazor WebAssembly and Javascript interop. Supports all Javascript data types and web browser APIs.
https://blazorjs.spawndev.com
MIT License
111 stars 7 forks source link

Is there anyway to send a message from a service worker? #17

Closed dodyg closed 1 year ago

dodyg commented 1 year ago

It's not very clear from this whether it is possible to send a message from IMathService.

image

According to this PostEvent is only available via the worker itself. image

LostBeard commented 1 year ago

According to this PostEvent is only available via the worker itself.

I'm not sure where the misunderstanding lies here. Hopefully this clears it up.

Option 1

In your window context

var worker = await workerService.GetWebWorker();
worker.OnMessage += (sender, msg) =>
{
    // use msg.TargetName to get the message identifier used as the first parameter in ```SendEventToParents```
    if (msg.TargetName == "progress")
    {
        PiProgress msgData = msg.GetData<PiProgress>();
        piProgress = msgData.Progress;
        StateHasChanged();
    }
};

In your WebWorker context to send a message to the window that is listening

workerService.SendEventToParents("progress", new PiProgress { Progress = piProgress });

That code shows how a window can listen to messages from the worker and how to send messages to the window listening for those messages.

Option 2 (WebWorker only, not available in SharedWebWorker)

Another option is to use WebWorkerService.DedicatedWorkerParent from inside a WebWorker.

WebWorkerService.DedicatedWorkerParent is equivalent to WebWorkerService.GetWebWorker except the returned value points to the Window context that created the WebWorker instead of a new WebWorker.

From inside a WebWorker context, to get an interface that allows calling a Service on the Window context from a WebWorker context just like a Window can do with a WebWorker.

// get a handle to the service interface ISomeWindowService in the Window context
var someWindowService = WebWorkerService.DedicatedWorkerParent.GetService<ISomeWindowService>(); 
// call a method on the window context
await someWindowService.SomeMethod();

Hopefully that helps. If you see a way to make the documentation more understandable please let me know. Thank you.

dodyg commented 1 year ago

public interface ISomeWindowService 
{
   Task DoSomethingAsync();
}

public class SomeWindowService: ISomeWindowService
{
   public async Task DoSomethingAsync()
   {
       //is there any mechanism that allows me to post a message from inside this method?     
   }
}
LostBeard commented 1 year ago

The window that created the WebWorker should already have a handle to the WebWorker but you can get the caller using a special parameter.

LostBeard commented 1 year ago
public interface ISomeWindowService 
{
   Task DoSomethingAsync(ServiceCallDispatcher caller);
}

public class SomeWindowService: ISomeWindowService
{
   public async Task DoSomethingAsync(ServiceCallDispatcher caller)
   {
        // caller will be the WebWorker context that called the method. 
        // it must be named caller and be of type ServiceCallDispatcher but it can be the first, last, or even middle parameter
        // the dispatcher auto inserts it when the method is called
        // when calling DoSomethingAsync you would call it with a null in the caller parameter place. Ex. DoSomethingAsync(null)

        // send message to OnMessage event handler of the caller (requires it is listening for it)
        // web workers can attach a listener via WebWorkerService.DedicatedWorkerParent.OnMessage
        // window can attach a listener after the worker is created via worker.OnMessage
        caller.SendEvent("someevent", someEventData);

        // OR
        // using a service to call method on the caller context
        var callerService = caller.GetService<ISomeServiceOnTheCaller>();
        await callerService.SomeMethodInCallerContext();
   }
}
LostBeard commented 1 year ago

That mechanism works in a WebWorker, SharedWebWorker, and Window contexts to get the caller context.

dodyg commented 1 year ago

https://github.com/dodyg/practical-aspnetcore/issues/377

dodyg commented 1 year ago

Thank you so much for your help. This is a brilliant library.

LostBeard commented 1 year ago

Thank you and glad to help. I will continue to work on improving the documentation. Some of these advanced features haven't quite made it into the docs yet but should be there soon.