rundll32
@rundll32

Проблема с вложенными промисами?

Мне нужно брать информацию из апи и выводить в рендер. Первый промис получает диалоги, а вложенный промис уже для каждого диалога в цикле тащит данные дополнительные из апи. Все это находится внутри componentDidMount, но в результате не происходит обновления карточек, а данные, судя по скрину, не успевают прогружаться.
componentDidMount() {
    // first request
    fetch(`${this.WebApiHost}/api/dialogs/get/${this.CurrentContactId}`)
    .then(function(res) {
      return res.json();
    })
    .then((json) => {
      if (!json || json.error == true) {
        console.log("error");
      } else {
        // first request is ok!
        this.state.Dialogs = [];
        // for each dialog
        json.dialogs.map((v) => {
          let dialogId = v.dialogId;
          // second request
          fetch(`${this.WebApiHost}/api/qwe/dialogs/${dialogId}/${this.My_Token}`)
          .then((res) => {
            let jsonRes = res.json();
            console.log(jsonRes);
            return jsonRes;
          })
          // second request is ok
          .then((json2) => {
            let data = json2.data;
            let msgDate = data == null ? "" : data.last_message.created;
            let msgText = data == null ? "" : data.last_message.text;
            this.state.Dialogs.push({dialogId:v.dialogId, from:v.transportName, date:msgDate, msg:msgText});
          })
          .catch((err) => {
            this.setState({IsLoading:false, Error:err});
          });
        });
      }
    }).then(() => {
      console.log("end");
      console.log(this.state.dialogs);
      this.setState({IsLoading:false});
    })
    .catch((err) => {
      this.setState({IsLoading:false, Error:err});
    });
  }

6200f727eeb93152896691.png
  • Вопрос задан
  • 93 просмотра
Пригласить эксперта
Ответы на вопрос 1
@GrayHorse
Нужно дождаться выполнения всех fetch().then().then(), собрав их в массиве.
const promises /* !!! */ =  json.dialogs.map((v) => {
    let dialogId = v.dialogId;
    return /* !!! */ fetch(`${this.WebApiHost}/api/qwe/dialogs/${dialogId}/${this.My_Token}`)
    // ....
});
await Promise.allSettled(promises);


А лучше переписать на async/await и не использовать асинхронные функции в map/forEach:
try {
    const resp = await fetch("");
    const json = await resp.json();
    if (!json || json.error === true) {
        console.log("error");
    }

    async function handleDialog(dialog) {
        try {
            const resp = await fetch("");
            const json = await resp.json();
            // ...
        } catch (e) {
            // ...
        }
    }

    const concurrently = false;
    if (concurrently) {
        // [Way 1] Run one by one ---------
        for (const dialog of []) {
            await handleDialog(dialog);
        }
    } else {
        // [Way 2] Run all concurrently ---
        const promises = [];
        for (const dialog of []) {
            promises.push(handleDialog(dialog));
        }
        await Promise.allSettled(promises);
    }
    // The best way: concurrently with limitation
    // @see https://qna.habr.com/q/1105356#answer_2098042

    // ...
} catch (e) {
    // ...
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы