Как работает await promisify (setTimeout) (ms) при отсутствии обратного вызова?

Aug 19 2020

Для простой асинхронной функции сна в JavaScript await promisify(setTimeout)(ms)работает!

Но как? Аргументы выглядят неверно.

  • promisify передает обратный вызов ошибки, поэтому
  • вызов setTimeout будетsetTimeout(ms, errorCallback)

который не должен работать, но работает. Как?


import { promisify } from 'util'
(async () => {
  // const start = Date.now()
  await promisify(setTimeout)(1000)
  // console.log(Date.now() - start)
})()
node <<HEREDOC
  (async () => {
    // const start = Date.now();
    await require('util').promisify(setTimeout)(1000);
    // console.log(Date.now() - start);
  })()
HEREDOC

Фон: await setTimeout(() => {}, 1000) не работает . Эта однострочная фраза : await new Promise(resolve => setTimeout(resolve, 1000))у меня не сработало (почему?). Мы можем обещать это вручную :, const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); await sleep(1000)но это дополнительная функция . Мы можем лучше.

Ответы

1 snak Aug 20 2020 at 00:31

Это потому, что setTimeoutтеперь есть настраиваемая обещанная функция . Вы можете найти его при печати setTimeout.

> console.log(setTimeout)
{ [Function: setTimeout] [Symbol(util.promisify.custom)]: [Function] }
undefined

Общие функции, которые принимают обратный вызов нестандартным образом, могут иметь пользовательскую обещанную функцию и util.promisifyвозвращать ее, когда функция имеет пользовательскую обещанную функцию.

PatrickFisher Aug 20 2020 at 00:39

setTimeoutэто особый случай для promisify.

Согласно спецификациям node.js :

Примечание: у этого метода есть собственный вариант обещаний, который доступен с помощью util.promisify ().

const util = require('util');
const setTimeoutPromise = util.promisify(setTimeout);

setTimeoutPromise(40, 'foobar').then((value) => {
 // value === 'foobar' (passing values is optional)
 // This is executed after about 40 milliseconds.
});

С async / await это становится:

await promisify(setTimeout)(1000)