Asyn c Выборка данных при установке свойства в Blazor - PullRequest
0 голосов
/ 13 июля 2020

Как правильно извлекать данные из асинхронного c метода при изменении значения свойства? В настоящее время я делаю что-то вроде этого.

  <form>
      <select class="form-control" @bind="DayFilter">
         <option>None</option>
         <option>Monday</option>
         <option>Tuesday</option>
         <option>Wednesday</option>
         <option>Thursday</option>
         <option>Friday</option>
         <option>Saturday</option>
         <option>Sunday</option>
       </select>
  </form>

@code
{
    private string dayFilter = NoDayFilter;
    private string DayFilter
    {
        get => dayFilter;
        set
        {
            dayFilter = value;
            _ = GetData();
        }
    }

private async Task GetData()
{
   ....
   StateHasChanged();
}

}

Полагаю, это неверно согласно Blazor Docs :

Асинхронная работа при применении значений параметров и свойств должна происходить во время события жизненного цикла OnParametersSetAsyn c.

Ответы [ 3 ]

0 голосов
/ 13 июля 2020

Вы используете GetData как async void. Возможно, но не рекомендуется. Я бы избегал этого шаблона «выстрелил и забыл» и вместо этого использовал бы событие onchange:

<select class="form-control"  @onchange="OnChange"> ... </select>  

async Task OnChange(ChangeEventArgs e)
{
    DayFilter = (string) e.Value;
    await GetData();
}
    
async Task GetData()
{
   .... // await stuff 
}

Больше не нужно вызывать StateHasChanged.

0 голосов
/ 13 июля 2020

Вызов асинхронного c метода из установщика свойств определенно не подходит, если вы хотите, чтобы пользовательский интерфейс обновлялся. Поразмыслив над ответами, которые дали enet и Хенк Холтерман, я добавил отладочный код

    set
    {
        dayFilter = value;
        _ = GetData();
        Debug.WriteLine("Day Filter After GetData()");
    }

    private async Task GetData()
    {
         Debug.WriteLine("Before http");
         var temp = await Http.GetFromJsonAsync<DailyData[]>("https://...");
         Debug.WriteLine("After http");
         ...
     }

, который дал следующий результат:

  • До http
  • Дневной фильтр после GetData ()
  • После http

Исходя из этого, я думаю, что пользовательский интерфейс завершил обновление до того, как были получены данные. Поскольку нет возможности ожидать от установщика, мое исходное решение не работает без вызова StateHasChanged, чего я хочу избежать, поскольку я думаю, что это приведет к множественным обновлениям пользовательского интерфейса.

0 голосов
/ 13 июля 2020

Ваши сомнения относительно правильности использования вызовов asyn c на самом деле не связаны с методами жизненного цикла компонентов ...

То, что вы делаете, нормально, и должно работать. Если вы используете ключевое слово asyn c, ваш метод будет асинхронным ... Но вам не нужно вызывать метод StateHasChanged. Он вызывается автоматически, когда задействованы события пользовательского интерфейса и когда используется метод asyn c: если вы используете метод asyn c, вы должны дождаться вызываемого метода, например:

private async Task GetData()
{
   forecasts = await httpClient.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
}

Когда среда выполнения выполняет этот метод и замечает ключевое слово ожидания, оно передает управление вызывающему коду ... Когда метод GetFromJsonAsyn c возвращается, выполнение продолжается синхронно до конца метода ... Также метод StateHasChanged является вызывается автоматически, и ваш компонент подвергается повторной визуализации.

Единственная проблема, которую я обнаружил в вашем коде, - это вызов GetData () из установленного средства доступа. Это работает и все такое, но я бы вызвал GetData () из обработчика событий, установленного для выбора нового элемента (события изменения). . Но вы должны использовать ключевое слово await в своем методе GetData, поэтому вам нужно вызвать StateHasChanged вручную, без чего компонент не сможет узнать, когда вызов завершен. Думаю, если вы поместите await Task.CompletedTask;, вы решите проблему.

Я действительно рассматривал возможность использования события OnChange, но мне нравится эстетика подхода привязки свойств

событие «изменение», да?

Какая эстетика? В любом случае компилятор создаст для вас другой код с атрибутом value и событием onchange.

Надеюсь, это поможет! Если вы застряли, дайте мне знать

...