Подождите, пока все подпромисы не будут разрешены

Скажем, у меня есть что-то вроде:

const exampleFunction = () => {
const fetchActions = someArray.map(() => {
                dispatch(action()).then(response => {
                    if (response?.data) {
                        dispatch(subAction({response: response.data}))
                    }
                })
            })

return Promise.all(fetchActions)
.then(()=> dispatch(finalAction()))
}

Моя проблема в том, что когда я отправляю свой finalAction, все действия были отправлены/разрешены, но не поддействия. Как я могу выполнить свою отправку (finalAction ())) ТОЛЬКО после того, как все действия и поддействия были разрешены?

🤔 А знаете ли вы, что...
JavaScript можно использовать для создания ботов и автоматизации задач в браузерах с помощью Puppeteer.


50
2

Ответы:

Проблема с вашим кодом в том, что вы ничего не возвращаете из обратного вызова someArray.map, а это означает, что fetchActions — это массив неопределенных значений, а не обещаний. Поэтому Promise.all не будет ждать завершения действий по отправке или поддействий перед разрешением.

Чтобы решить эту проблему, вы можете попробовать следующее:

const exampleFunction = async () => {
  const fetchActions = someArray.map(async () => {
    const response = await dispatch(action());
    if (response?.data) {
      await dispatch(subAction({ response: response.data }));
    }
  });

  await Promise.all(fetchActions);
  await dispatch(finalAction());
};

В этом коде someArray.map ничего не возвращает, но создает массив обещаний. Каждое обещание ожидает последнего ожидания внутри функции карты, то есть либо dispatch(subAction()), либо undefined. Это похоже на возврат массива этих значений в виде промисов.


Если вы хотите сделать это более явным, вы можете добавить оператор return внутри обратного вызова карты, например:

const fetchActions = someArray.map(async () => {
  const response = await dispatch(action());
  if (response?.data) {
    return dispatch(subAction({ response: response.data }));
  }
  return undefined;
});

Решено

Проблема в том, что Promise.all([...promises]) разрешается, когда все promises разрешаются, но ваш fetchActions на самом деле не является массивом промисов (как вы задумали), потому что у них есть осиротевшие промисы с отключенной цепочкой промисов. Для того, чтобы снова соединить цепочку, нужно добавить return.

const exampleFunction = () => {
  const fetchActions = someArray.map(() => {
    return dispatch(action()).then(response => {
      if (response?.data) {
        return dispatch(subAction({
          response: response.data
        }))
      }
    })
  })

  return Promise.all(fetchActions)
    .then(() => dispatch(finalAction()))
}

См. здесь, чтобы узнать больше о цепочке промисов.


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

Например:

const promiseA = () => {
  promiseY();
};

const promiseB = () => {
  promiseZ();
};

await Promise.all([promiseA(), promiseB()]);

Promise.all выше немедленно разрешается, не дожидаясь promiseY или promiseZ, потому что они осиротевшие промисы.

Для того, чтобы дождаться их, должно быть так:

const promiseA = () => {
  return promiseY();
};

const promiseB = () => {
  return promiseZ();
};

await Promise.all([promiseA(), promiseB()]);