Синхронно ли отправлять три действия внутри функций onClick, а затем отображать данные, используя эти ответы? - PullRequest
0 голосов
/ 04 ноября 2019

Я хочу проанализировать один лист Excel, и перед синтаксическим анализом я хочу, чтобы некоторые данные из бэкэнда отобразили его.

Поэтому после нажатия кнопки «Отправить» я хочу запустить три действия одно за другим и сохранить ответ внутрихранить. Я использую Redx-сагу для этого. После трех действий (вызовы API) я вызову функцию синтаксического анализа и выполню синтаксический анализ и отображение, используя ответ, который я получу из хранилища.

Я попытался отправить три действия одно за другим. Но как только он достигает сетевого клиента, то есть экземпляра axios для вызова API, он становится асинхронным и выполняется следующая строка.

onSubmit = () => {

/*  I will set the loader on submit button till the api is called and all parsing of excel sheet is done. */

  this.setState({
    showLoader: true,
  }, () => {
    this.props.getData1(); //Will be saving it in store as data1
    this.props.getData2(); //Will be saving it in store as data2
    this.props.getData3(); //Will be saving it in store as data3

 /* After this I want to call the parsing function to parse the excel sheet data and map accordingly */

  parseExcelData(sheetData); //sheet data is the excel data
}

Поэтому я ожидал, что когда я вызову функцию 'parseExcelData', данныеиз хранилища, т.е. данные1, данные2 и данные3 будут доступны в этой функции. Но все вызовы API происходят после разбора листа. Я сделал это с помощью функций генератора саги и работает нормально. Но я хочу знать, как справиться с этой ситуацией с помощью приставки.

1 Ответ

0 голосов
/ 05 ноября 2019

Помещение вызова API (или любой другой асинхронной операции) в сагу не делает это действие синхронным, оно все еще является асинхронным. Отдельно, redux-сага на самом деле не поддерживает получение результата от действия - вы запускаете сагу с действием, поэтому, когда сага завершается, она не может вернуть результат в код, который его первоначально инициировал. (Вы можете попытаться обойти это, передав обратный вызов вместе с действием, запускающим сагу, и заставив сагу вызвать обратный вызов, но я бы не рекомендовал такой подход.)

Я бы рекомендовал реализовать этобез redux-saga, с использованием традиционных действий создателей. Создатели действий будут возвращать обещания, которые делают асинхронные вызовы API, и разрешатся с результатом, когда они будут завершены. Это может выглядеть примерно так:

// action creator getData1, getData2, getData3
export const getData1 = () => {
  return fetch(apiUrl).then(result => {
    return result.json();
  }).then(resultJson => {
    // also fire an action to put it in the store here
    // if other parts of your app need the data
    return resultJson;
  }).catch(err => {
    console.error(err);
  });
};

// react component
// assumes 1, 2, and 3 cannot be parallelized
// could also be written with .then instead of await
onSubmit = async () => {
  this.setState({showLoader: true}, () => {
    const result1 = await this.props.getData1();
    const result2 = await this.props.getData2(result1);
    const result3 = await this.props.getData3(result2);
  });
}

Вы можете попросить создателей действий отправить действие в хранилище данных вместо для разрешения обещания с результатом. Но это означает, что вы должны получить новые данные через реквизиты компонента, что, вероятно, означает что-то в componentDidUpdate, которое проверяет, отличаются ли новые реквизиты от старых реквизитов, и, если так, вызывает следующий сборщик данных. ИМО такой подход гораздо более неловкий.

...