Почему мой цикл do.. while не выполняет корректно setTimeout в коде async-await? - PullRequest
1 голос
/ 25 апреля 2019

У меня есть цикл do.. while, который выполняет обещание и ожидает ответа. Цикл должен продолжаться, пока ответ либо «Обрабатывается», либо «Получен». Однако в Promise есть функция setTimeout.

Целью здесь является то, что функция respo = await promise1.then(resp => resp) в операторе "do" цикла do.. while вызывается только через 2 секунды. Это просто для того, чтобы позволить API, который я использую, завершить свою работу.

В настоящее время происходит то, что setTimeout вызывается один раз, и цикл продолжает повторять тот же самый ответ практически сразу, указывая, что 2-секундный перерыв не работает.

Что я делаю не так?

const promise1 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve(tasks(resStatus.data.task.id, tokenTenant))
  }, 2000);
})

do {
  respo = await promise1
  console.log(respo.data)
} while (respo.data.status === "Processing" || respo.data.status === "Received");

. , .

Некоторые примеры ответов (проблема решена) для любопытных:

ALL SYSTEMS GO!
{ id: 'd23b2cf3-02c3-48fe-9479-1407238d41d9',
  status: 'Received',
  result: null,
  tenant_id: 'eaa55f40-93fa',
  creation_time: '2019-04-25T18:19:47+0000' }

****...some results omitted for brievety...****

{ id: 'd23b2cf3-02c3-48fe-9479-1407238d41d9',
  status: 'Processing',
  result: null,
  tenant_id: 'eaa55f40-93fa',
  creation_time: '2019-04-25T18:19:47+0000' }
{ id: 'd23b2cf3-02c3-48fe-9479-1407238d41d9',
  status: 'Failed',
  result: { Reason: '[Errno 22] Invalid argument' },
  tenant_id: 'eaa55f40-93fa',
  creation_time: '2019-04-25T18:19:47+0000' }

Ответы [ 2 ]

4 голосов
/ 25 апреля 2019

Это одно из наиболее распространенных заблуждений об обещаниях. Это не с использованием обещания, которое вызывает функцию, которую вы передаете в new Promise ( функция исполнителя как она вызывается), это создание обещания. Этот код (в исполнителе) также вызывается синхронно: setTimeout вызывается до того, как promise1 получает обещание (а затем его обратный вызов происходит примерно через две секунды).

В вашем коде вы настраиваете один setTimeout вызов, а затем ждете его завершения, а затем, если цикл повторяется, вы ждете того же самого результата второй раз. (Конечно, вы получите его намного быстрее, потому что тайм-аут уже завершен.)

Чтобы повторить операцию, вам нужно создать обещание в пределах вашего цикла, чтобы вы повторно запустили код в функции executor:

function getTask() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve(tasks(resStatus.data.task.id, tokenTenant))
    }, 2000);
  });
}

do {
  respo = await getTask();
  console.log(respo.data)
} while (respo.data.status === "Processing" || respo.data.status === "Received");

Для ясности я использовал традиционную функцию для getTask. Если хотите, вы можете вместо этого сделать функцию стрелки (вместе с другими):

const getTask = () => new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(tasks(resStatus.data.task.id, tokenTenant))
  }, 2000);
});
4 голосов
/ 25 апреля 2019

Несколько замечаний:

  • обещание может быть выполнено только один раз.
  • обратный вызов, переданный конструктору Promise, выполняется немедленно, а затем никогда не повторяется

Решение: переместите определение const promise1 = ... в цикл.Таким образом, вы создаете новое обещание на каждой итерации.

...