コールバックが欠落している場合、 `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持っているカスタムpromisified機能を今すぐ。印刷すると見つかります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()を使用して使用できるpromiseのカスタムバリアントがあります。

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)