【问题标题】:Calling an async function from a sync function从同步函数调用异步函数
【发布时间】:2020-04-20 03:29:44
【问题描述】:

我正在构建 Blazor 客户端应用程序。我正在使用MatBlazor 组件。

我在一个页面上有两个 MatSelectString 控件。第一个用于选择类别,第二个用于从类别中选择产品。所以我把它设置成这样:

<MatSelect Outlined="true" Label="Category" @bind-Value="@Category">
    <MatOptionString></MatOptionString>
    @foreach (var cat in GetCategories())
    {
        <MatOptionString Value="@cat">@cat</MatOptionString>
    }
</MatSelect>
<MatSelect Outlined="true" Disabled="@(!string.IsNullOrWhiteSpace(Category))" Label="Product" @bind-Value="@Product" >
    <MatOptionString></MatOptionString>
    @foreach (var prod in GetProducts(Category))
    {
        <MatOptionString Value="@prod">@prod</MatOptionString>
    }
</MatSelect>

GetProducts(Category) 代码中,我想调用后端。问题是只有一个HttpClient.GetJsonAsync&lt;&gt;() 方法,不能从非异步方法中调用。但是 GetProduct() 不能异步。

我尝试过的事情:

  • 将对我的函数的调用放在异步 lambda 中(不允许在 foreach 或其他代码块中使用)
  • 使用 Task.Result(挂起)
  • 将后端调用放在其他组件级异步事件中(被多次调用)

有什么想法吗?

【问题讨论】:

    标签: async-await blazor blazor-client-side matblazor


    【解决方案1】:

    你可以使用ValueChangedEventCallback:

    <MatSelect 
        Outlined="true" 
        Label="Category" 
        ValueChanged="(string i)=>OnChangeCategory(i)"> @* <-- here *@
        <MatOptionString></MatOptionString>
        @foreach (var cat in GetCategories())
        {
            <MatOptionString Value="@cat">@cat</MatOptionString>
        }
    </MatSelect>
    
    @code
    {
       protected async Task OnChangeCategory(string newValue)
       {
          this.Category = newValue;
          // call backend async tasks
          // ...
       }
    

    查看blazorfiddle.com

    【讨论】:

    • 使用以下方法将整数优雅地转换为字符串内联的额外点:"(string i)=>" ??
    • 感谢@MichaelWashington 欣赏? 大多数 Matblazor 控件都是通用的,在匿名函数上没有显式类型,它无法推断类型。
    • @daniherrera 如果您在 MatBlazor 上提交 PR 作为示例,那就太好了。
    • @daniherrera 我正在 WebAssembly 项目中尝试您的代码,我收到此错误“未处理的异常呈现组件:MatBlazor.MatSelect1[System.Nullable1[System.Int64]] 需要 ' 的值ValueExpression' 参数。通常在使用 'bind-Value' 时自动提供。"。知道为什么它还需要一个 ValueExpression 参数吗?
    • 这是我的代码&lt;MatSelect Label="@strings.Authority" ValueChanged="(Int64? nv)=&gt;OnChangeAuthority(nv)" &gt; @if (Authorities != null) @foreach (var au in Authorities) { &lt;MatOption TValue="Int64?" Value="@au.Id"&gt;@au.Name&lt;/MatOption&gt; } &lt;/MatSelect&gt;