最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - JSRuntime.InvokeVoidAsync in Blazor Server app calling multiple functions when I only tell it to call one - Stack O

programmeradmin1浏览0评论

I have a Blazor server app with two buttons. The first button calls the MenuOpen method in C#, and the second calls the TestJSInterop method in C#. Here is the code:

@inject IJSRuntime JSRuntime;

<!-- buttons -->

@code {
    List<int> tabs = new List<int>();

    protected override Task OnAfterRenderAsync(bool firstRender)
    {
        JSRuntime.InvokeVoidAsync("monacoInit");
        return base.OnAfterRenderAsync(firstRender);
    }

    async Task OpenNewTab(string title)
    {
        int newId = await JSRuntime.InvokeAsync<int>("addEditorModel", new object[]
        {
            title, "test", "test", "test"
        });
        tabs.Add(newId);
        await JSRuntime.InvokeVoidAsync("addTab", newId);
    }

    async Task MenuOpen()
    {
        await OpenNewTab("testing");
    }

    async Task TestJSInterop()
    {
        await JSRuntime.InvokeVoidAsync("console.log", "test");
    }
}

In the Javascript, I've added console.logs to each method that's being called from C#. When I press the button to call TestJSInterop, I get the following result in the console:

test

call addEditorModel

call addTab: parameter is 0

call addEditorModel

call addTab: parameter is 0

When I press the button to call MenuOpen, I get this result:

call addEditorModel

call addTab: parameter is 1

call addEditorModel

call addTab: parameter is 0

call addEditorModel

call addTab: parameter is 0

I know that the OpenNewTab C# method is not being called multiple times, as when I put a breakpoint there and click the button to call TestJSInterop I do not reach the breakpoint.

The JSRuntime.InvokeVoidAsync call does work correctly in OnAfterRenderAsync.

Why am I getting this behavior?

I have a Blazor server app with two buttons. The first button calls the MenuOpen method in C#, and the second calls the TestJSInterop method in C#. Here is the code:

@inject IJSRuntime JSRuntime;

<!-- buttons -->

@code {
    List<int> tabs = new List<int>();

    protected override Task OnAfterRenderAsync(bool firstRender)
    {
        JSRuntime.InvokeVoidAsync("monacoInit");
        return base.OnAfterRenderAsync(firstRender);
    }

    async Task OpenNewTab(string title)
    {
        int newId = await JSRuntime.InvokeAsync<int>("addEditorModel", new object[]
        {
            title, "test", "test", "test"
        });
        tabs.Add(newId);
        await JSRuntime.InvokeVoidAsync("addTab", newId);
    }

    async Task MenuOpen()
    {
        await OpenNewTab("testing");
    }

    async Task TestJSInterop()
    {
        await JSRuntime.InvokeVoidAsync("console.log", "test");
    }
}

In the Javascript, I've added console.logs to each method that's being called from C#. When I press the button to call TestJSInterop, I get the following result in the console:

test

call addEditorModel

call addTab: parameter is 0

call addEditorModel

call addTab: parameter is 0

When I press the button to call MenuOpen, I get this result:

call addEditorModel

call addTab: parameter is 1

call addEditorModel

call addTab: parameter is 0

call addEditorModel

call addTab: parameter is 0

I know that the OpenNewTab C# method is not being called multiple times, as when I put a breakpoint there and click the button to call TestJSInterop I do not reach the breakpoint.

The JSRuntime.InvokeVoidAsync call does work correctly in OnAfterRenderAsync.

Why am I getting this behavior?

Share Improve this question edited Apr 19, 2020 at 19:39 Merlin04 asked Apr 19, 2020 at 18:40 Merlin04Merlin04 2,3374 gold badges24 silver badges32 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

I was trying to understand your partial code, but it seems as though I've failed. However, you should take into account the following:

  1. The OnAfterRenderAsync method is executed each time your ponent is being rendered. It is primarily used to initialize JavaScript objects. When you want to initialize your JavaScript objects (I guess only once, right ?), the code should be placed within an if statement checking that this is the first time:

    if( firstRender )
       {
           // Here's you place code that is executed only once
           // the parameter firstRender is evaluted to true only the first time 
           // the OnAfterRenderAsync method is executed
        }
    
  2. Only UI events, such as the click event, cause your ponent to re-render. If you need to re-render your ponent in order to see changes made otherwise, you'll have to call the StateHasChanged method

  3. If your app is pre-rendering ( render-mode="ServerPrerendered" ), your ponents are rendered twice, and thus you may see messages printed in the console window twice. This is OK.

Hope this helps... If you did not solve your issues, please post a plete repo of your code, and I'll try to help you with this.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论