使用 util.promisify 承诺自定义函数
Promisifying custom functions with util.promisify
我想使用 util.promisify 来承诺自定义函数。但是,util.promisify 适用于将错误优先回调作为最后一个参数的节点样式方法。我如何调整我的自定义函数,以便它们可以与 util.promisify 一起使用?
How can I adjust my custom functions so that they will work with util.promisify?
我的第一选择是添加一个新的 API,returns 一个承诺 - 将您自己的 API 包装在一个新的 Promise 构造函数中。然后,您就有了一个文档化的、返回承诺的 API,它的使用方法很明显,客户不需要额外的步骤就可以使用它。
但是,如果您真的想制作与 util.promisify()
兼容的东西,请继续阅读...
如果您已经显示了您希望 util.promisify()
使用的函数的调用约定,我们可以专门为该代码提供自定义实现,但由于您没有,下面是一个示例实现.
文档中描述了一般概念 here,但我不会确切地说文档非常清楚事情是如何工作的。这是一个例子。
假设您有一个计时器函数,它按以下顺序接受三个参数:
timer(callback, t, v)
其中 t
是计时器的时间(以毫秒为单位),v
是计时器触发时它将传递给回调的值。并且,它按顺序向回调传递两个值 callback(v, err)
。而且,是的,这个特定的计时器有时会反馈错误。
注意,具体来说,回调作为第一个参数传递,回调本身得到 err
作为第二个参数,这两者显然与 util.promisify()
的默认实现不兼容(对于本演示的目的),因为它们不符合 nodejs 异步调用约定。
这是不遵循 nodejs 调用约定的此计时器(非承诺)函数的示例用法:
// example
timer((v, err) => {
console.log(v, err); // outputs "hi", null
}, 2000, "hi");
为了使其与 util.promisify()
兼容,我们可以创建一个自定义的 promisify 行为,如下所示:
// define promise returning implementation of timer that leaves out
// the callback argument, but takes the same other arguments
timer[util.promisify.custom] = (t, v) => {
return new Promise((resolve, reject) => {
timer((value, err) => {
if (err) {
reject(err);
} else {
resolve(value);
}
}, t, v);
});
};
一般概念是,当您将函数引用传递给 util.promisify(fn)
时,它会查找 fn[util.promisify.custom]
,如果存在,它将使用该 promisify 实现而不是默认实现。如果您想知道 util.promisify.custom
是什么,它是由 util
库定义的符号 - 只是一个唯一的 属性 名称,您可以将其作为 属性 分配给您自己的函数为了确定您已经实现了自定义 promisify 功能。由于符号在任何 nodejs 实现中都是唯一的,因此将 属性 添加到您的函数中不会干扰任何其他属性。
其他呼叫者可以像这样使用:
const timerP = util.promisify(timer);
// you call timerP, leaving out the callback argument
timerP(3000, "bye").then(result => {
console.log(result); // outputs "bye" after 3000ms
}).catch(err => {
console.log(err);
});
如果你想看到 util.promisify()
的 nodejs 实现,你可以在实际 util.js code.
中看到它
我想使用 util.promisify 来承诺自定义函数。但是,util.promisify 适用于将错误优先回调作为最后一个参数的节点样式方法。我如何调整我的自定义函数,以便它们可以与 util.promisify 一起使用?
How can I adjust my custom functions so that they will work with util.promisify?
我的第一选择是添加一个新的 API,returns 一个承诺 - 将您自己的 API 包装在一个新的 Promise 构造函数中。然后,您就有了一个文档化的、返回承诺的 API,它的使用方法很明显,客户不需要额外的步骤就可以使用它。
但是,如果您真的想制作与 util.promisify()
兼容的东西,请继续阅读...
如果您已经显示了您希望 util.promisify()
使用的函数的调用约定,我们可以专门为该代码提供自定义实现,但由于您没有,下面是一个示例实现.
文档中描述了一般概念 here,但我不会确切地说文档非常清楚事情是如何工作的。这是一个例子。
假设您有一个计时器函数,它按以下顺序接受三个参数:
timer(callback, t, v)
其中 t
是计时器的时间(以毫秒为单位),v
是计时器触发时它将传递给回调的值。并且,它按顺序向回调传递两个值 callback(v, err)
。而且,是的,这个特定的计时器有时会反馈错误。
注意,具体来说,回调作为第一个参数传递,回调本身得到 err
作为第二个参数,这两者显然与 util.promisify()
的默认实现不兼容(对于本演示的目的),因为它们不符合 nodejs 异步调用约定。
这是不遵循 nodejs 调用约定的此计时器(非承诺)函数的示例用法:
// example
timer((v, err) => {
console.log(v, err); // outputs "hi", null
}, 2000, "hi");
为了使其与 util.promisify()
兼容,我们可以创建一个自定义的 promisify 行为,如下所示:
// define promise returning implementation of timer that leaves out
// the callback argument, but takes the same other arguments
timer[util.promisify.custom] = (t, v) => {
return new Promise((resolve, reject) => {
timer((value, err) => {
if (err) {
reject(err);
} else {
resolve(value);
}
}, t, v);
});
};
一般概念是,当您将函数引用传递给 util.promisify(fn)
时,它会查找 fn[util.promisify.custom]
,如果存在,它将使用该 promisify 实现而不是默认实现。如果您想知道 util.promisify.custom
是什么,它是由 util
库定义的符号 - 只是一个唯一的 属性 名称,您可以将其作为 属性 分配给您自己的函数为了确定您已经实现了自定义 promisify 功能。由于符号在任何 nodejs 实现中都是唯一的,因此将 属性 添加到您的函数中不会干扰任何其他属性。
其他呼叫者可以像这样使用:
const timerP = util.promisify(timer);
// you call timerP, leaving out the callback argument
timerP(3000, "bye").then(result => {
console.log(result); // outputs "bye" after 3000ms
}).catch(err => {
console.log(err);
});
如果你想看到 util.promisify()
的 nodejs 实现,你可以在实际 util.js code.