¿Cómo funciona `await promisify (setTimeout) (ms)` cuando falta la devolución de llamada?

Aug 19 2020

Para una función de suspensión asíncrona simple en JavaScript, await promisify(setTimeout)(ms)¡funciona!

¿Pero cómo? Los argumentos parecen incorrectos.

  • promisify pasa una devolución de llamada de error, por lo que el
  • setTimeout call seríasetTimeout(ms, errorCallback)

que no debería funcionar, pero lo hace. ¿Cómo?


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

Antecedentes: await setTimeout(() => {}, 1000) no funciona . Esta frase : await new Promise(resolve => setTimeout(resolve, 1000))no funcionó para mí (¿por qué?). Podemos prometerlo manualmente :, const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); await sleep(1000)pero esa es una función extra . Podemos hacerlo mejor.

Respuestas

1 snak Aug 20 2020 at 00:31

Esto se debe a que ahora setTimeouttiene una función prometida personalizada . Puede encontrarlo cuando imprime setTimeout.

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

Las funciones comunes que reciben una devolución de llamada que no es la forma estándar pueden tener una función prometida personalizada y la util.promisifydevuelven cuando una función tiene una función prometida personalizada.

PatrickFisher Aug 20 2020 at 00:39

setTimeoutes un caso especial para promisify.

Según las especificaciones de node.js :

Nota: Este método tiene una variante personalizada para promesas que está disponible usando 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.
});

Con async / await, eso se convierte en:

await promisify(setTimeout)(1000)