перенастройка обещания с использованием шаблона async await с некоторой задержкой

#javascript #asynchronous #promise #async-await #es6-promise

#javascript #асинхронный #обещание #async-await #es6-обещание

Вопрос:

Я пытаюсь вернуть некоторые тестовые данные из метода, который вызывает rest api. Чтобы имитировать вызов rest api, я добавляю некоторую задержку для возврата обещания с использованием шаблона async-await, но он работает не так, как ожидалось.

Мое понимание шаблона async-await в JavaScript заключается в том, что любое значение, возвращаемое из асинхронной функции, возвращается как обещание, поэтому значение 100 должно быть возвращено функцией как обещание, и поэтому последний оператор, использующий .then , должен показывать 100, но это не так.

Вопрос, что не так с приведенным ниже фрагментом кода, из-за которого отображается предупреждение в последней строке кода, undefined а не 100?

 async function f() {

  function delayedResponse() {
    setTimeout(function() { return 100}, 5000);
  }
  return await delayedResponse();

}

f().then(alert); // 100  

Комментарии:

1. delayedResponse ничего не возвращает -> undefined

2. Если нет явного Promise , возвращаемое значение будет автоматически обернуто в Promise . Если вы хотите «вернуть» что-то из setTimeout обратного вызова, вы должны использовать a Promise и разрешить его в обратном вызове.

3. ОК. Теперь я понял. Я должен использовать объект Promise. У меня сложилось впечатление, что я мог бы просто использовать async await без обещания, но теперь это ясно. Спасибо.

Ответ №1:

Вы ничего не возвращаете в своем delayedResponse , поэтому это привело undefined .

Вместо этого, чтобы достичь того, чего вы ожидаете, вы можете явно создать обещание и разрешить значение, используя тайм-аут;

 async function f() {
  return new Promise(resolve => {
    setTimeout(function() { resolve(100)}, 5000);
  }); 
}

f().then(alert); // 100  

Комментарии:

1. К вашему сведению, вы можете сделать setTimeout(resolve, 5000, 100); вместо объявления отдельной функции обратного вызова для setTimeout(function() { resolve(100)}, 5000); .

2. @jfriend00 точно!

Ответ №2:

NodeJS 14.x или API браузера

 async function delay(msecs: number) {
  return new Promise((resolve) => setTimeout(resolve, msecs));
}
  

NodeJS 16.x или более поздней версии

 import { setTimeout } from "timers/promises";
const result = await setTimeout(msecs, 'somevalue')
  

Обратите внимание, что порядок setTimeout() аргументов изменился!
Старое setTimeout() определено, если вы не импортируете из «таймеров / обещаний».

Ссылки