[英]difference between 'util.promisify(setTimeout)' and 'ms => new Promise(resolve => setTimeout(resolve, ms))'
Environment: node 8.11.x I want use async/await for sleep a while.环境:节点 8.11.x 我想使用异步/等待睡眠一段时间。
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
await sleep(5000)
This works.这有效。
const sleep = util.promisify(setTimeout)
await sleep(5000)
It cause a exception: TypeError: "callback" argument must be a function.它会导致异常:TypeError: "callback" 参数必须是一个函数。 setTimeout The document note: This method has a custom variant for promises that is available using util.promisify() setTimeout文档说明:此方法具有可使用 util.promisify() 获得的 promise 的自定义变体
So what's the difference?那么有什么区别呢?
promisify
is expects a function that has final argument that is the callback. promisify
期望一个具有作为回调的最终参数的函数。
In other a words it wants a function that looks like:换句话说,它需要一个如下所示的函数:
function takesACallback(str, Fn) {
Fn(null, "got: ", str)
// or with an error:
// Fn(error)
}
Of course setTimout
is the opposite.当然setTimout
正好相反。 The argument you want to pass in is the last argument.您要传入的参数是最后一个参数。 So when you try to call the promisify
d function and pass in an argument, it will take that argument -- the delay-- and try to call it like a function.因此,当您尝试调用promisify
d 函数并传入一个参数时,它将采用该参数 - 延迟 - 并尝试像调用函数一样调用它。 Of course that's an error.当然这是一个错误。
For entertainment (and slight educational) purposes only, you can pass in a function that reverses the arguments and it will work:仅出于娱乐(和轻微的教育)目的,您可以传入一个反转参数的函数,它会起作用:
let util = require('util')
let pause = util.promisify((a, f) => setTimeout(f, a))
pause(2000)
.then(() => console.log("done"))
Now the final argument of the function you passed to promisify
expects function.现在,您传递给promisify
的函数的最后一个参数期望函数。 But the asyn/await
method is so much nicer…但asyn/await
方法是如此好得多...
You know that this right here works:你知道这在这里有效:
const {promisify} = require('util');
const sleep = promisify(setTimeout);
;(async () => {
const ts = Date.now()
await sleep(5000)
console.log(Date.now()-ts)
})();
This works fine, why not go with it and use it???这工作正常,为什么不去使用它???
This can be a one-liner: await promisify(setTimeout)(1000)
.这可以是单行的: await promisify(setTimeout)(1000)
。
It works because setTimeout has a custom variant for promisify .它有效是因为 setTimeout 有一个自定义变体 promisify 。 It does work with node 8.11.它确实适用于节点 8.11。
nvm install 8.11 && nvm use 8.11
node <<HEREDOC
(async () => {
// const start = Date.now();
await require('util').promisify(setTimeout)(5000);
// console.log(Date.now() - start);
})()
HEREDOC
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
Is the essence of the implementation of util.promisify(setTimeout)
, but there are additional features to the promisify
implementation:是util.promisify(setTimeout)
实现的util.promisify(setTimeout)
,但是promisify
实现还有一些额外的特性:
setTimeoutPromisify(10, 'foo bar').then(value => console.log(value)) // logs "foo bar"
console.log(await setTimeoutPromisify(10, 'foo bar')) // logs "foo bar"
AbortController
signal
to cancel the timeout允许您指定AbortController
signal
以取消超时ref
, which if set to false, means the program will exit before the timeout finishes if nothing else is happening允许您选择是否保留ref
,如果设置为 false,则意味着如果没有其他事情发生,程序将在超时完成之前退出const controller = new AbortController();
const signal = ac.signal;
setTimeoutPromisify(1000, 'foo bar', { signal, ref: true })
.then(console.log)
.catch((err) => {
if (err.name === 'AbortError')
console.log('The timeout was aborted');
})
controller.abort()
For more information see https://nodejs.org/api/timers.html有关更多信息,请参阅https://nodejs.org/api/timers.html
The implementation in node 16 is below:节点 16 中的实现如下:
function setTimeout(after, value, options = {}) {
const args = value !== undefined ? [value] : value;
if (options == null || typeof options !== 'object') {
return PromiseReject(
new ERR_INVALID_ARG_TYPE(
'options',
'Object',
options));
}
const { signal, ref = true } = options;
try {
validateAbortSignal(signal, 'options.signal');
} catch (err) {
return PromiseReject(err);
}
if (typeof ref !== 'boolean') {
return PromiseReject(
new ERR_INVALID_ARG_TYPE(
'options.ref',
'boolean',
ref));
}
if (signal && signal.aborted) {
return PromiseReject(new AbortError());
}
let oncancel;
const ret = new Promise((resolve, reject) => {
const timeout = new Timeout(resolve, after, args, false, true);
if (!ref) timeout.unref();
insert(timeout, timeout._idleTimeout);
if (signal) {
oncancel = FunctionPrototypeBind(cancelListenerHandler,
timeout, clearTimeout, reject);
signal.addEventListener('abort', oncancel);
}
});
return oncancel !== undefined ?
PromisePrototypeFinally(
ret,
() => signal.removeEventListener('abort', oncancel)) : ret;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.