[英]difference between 'util.promisify(setTimeout)' and 'ms => new Promise(resolve => setTimeout(resolve, ms))'
環境:節點 8.11.x 我想使用異步/等待睡眠一段時間。
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
await sleep(5000)
這有效。
const sleep = util.promisify(setTimeout)
await sleep(5000)
它會導致異常:TypeError: "callback" 參數必須是一個函數。 setTimeout文檔說明:此方法具有可使用 util.promisify() 獲得的 promise 的自定義變體
那么有什么區別呢?
promisify
期望一個具有作為回調的最終參數的函數。
換句話說,它需要一個如下所示的函數:
function takesACallback(str, Fn) {
Fn(null, "got: ", str)
// or with an error:
// Fn(error)
}
當然setTimout
正好相反。 您要傳入的參數是最后一個參數。 因此,當您嘗試調用promisify
d 函數並傳入一個參數時,它將采用該參數 - 延遲 - 並嘗試像調用函數一樣調用它。 當然這是一個錯誤。
僅出於娛樂(和輕微的教育)目的,您可以傳入一個反轉參數的函數,它會起作用:
let util = require('util')
let pause = util.promisify((a, f) => setTimeout(f, a))
pause(2000)
.then(() => console.log("done"))
現在,您傳遞給promisify
的函數的最后一個參數期望函數。 但asyn/await
方法是如此好得多...
你知道這在這里有效:
const {promisify} = require('util');
const sleep = promisify(setTimeout);
;(async () => {
const ts = Date.now()
await sleep(5000)
console.log(Date.now()-ts)
})();
這工作正常,為什么不去使用它???
這可以是單行的: await promisify(setTimeout)(1000)
。
它有效是因為 setTimeout 有一個自定義變體 promisify 。 它確實適用於節點 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))
是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
以取消超時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()
有關更多信息,請參閱https://nodejs.org/api/timers.html
節點 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.