Bagaimana cara kerja `await promisify (setTimeout) (ms)` saat callback hilang?

Aug 19 2020

Untuk fungsi tidur asinkron sederhana di JavaScript, await promisify(setTimeout)(ms)berhasil!

Tapi bagaimana caranya? Argumennya terlihat salah.

  • promisify melewati callback error, jadi
  • panggilan setTimeout akansetTimeout(ms, errorCallback)

yang seharusnya tidak berfungsi, namun berhasil. Bagaimana?


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

Latar belakang: await setTimeout(() => {}, 1000) tidak berfungsi . Ini satu-liner : await new Promise(resolve => setTimeout(resolve, 1000))tidak bekerja untuk saya (mengapa?). Kita bisa promisify secara manual : const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); await sleep(1000), tapi itu adalah fungsi ekstra . Kami bisa lebih baik.

Jawaban

1 snak Aug 20 2020 at 00:31

Ini karena sekarang setTimeoutmemiliki fungsi yang dijanjikan khusus . Anda dapat menemukannya saat mencetak setTimeout.

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

Fungsi umum yang menerima panggilan balik tidak dengan cara standar mungkin memiliki fungsi yang dijanjikan khusus, dan util.promisifymengembalikannya ketika suatu fungsi memiliki fungsi yang dijanjikan khusus.

PatrickFisher Aug 20 2020 at 00:39

setTimeoutadalah kasus khusus untuk promisify.

Sesuai spesifikasi node.js :

Catatan: Metode ini memiliki varian khusus untuk promise yang tersedia menggunakan 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.
});

Dengan async / await, itu menjadi:

await promisify(setTimeout)(1000)