我想使用promises,但我有一个回调API,格式如下:
1. DOM加载或其他一次性事件:
window.onload; // set to callback
...
window.onload = function() {
};
2.普通回调:
function request(onChangeHandler) {
...
}
request(function() {
// change happened
...
});
3.节点样式回调(“nodeback”):
function getStuff(dat, callback) {
...
}
getStuff("dataParam", function(err, data) {
...
})
4.具有节点样式回调的整个库:
API;
API.one(function(err, data) {
API.two(function(err, data2) {
API.three(function(err, data3) {
...
});
});
});
17 回答
kriskowal的Q库包括回调承诺函数 . 像这样的方法:
可以用Q.ninvoke转换
你可以做这样的事情
然后使用它
今天,我可以在
Node.js
中使用Promise
作为普通的Javascript方法 .一个简单的基本示例
Promise
(使用 KISS 方式):Plain Javascript异步API代码:
Promise Javascript异步API代码:
(我建议访问this beautiful source)
Promise
也可以与ES7
中的async\await
一起使用,以使程序流等待fullfiled
结果,如下所示:使用
.then()
方法使用相同代码的另一种用法Promise
也可以在任何基于Node.js的平台上使用,例如react-native
.希望这可以帮助 .
使用简单的旧vanilla javaScript,这是一个宣传api回调的解决方案 .
在Node.js 8.0.0的候选版本中,有一个新的实用程序,
util.promisify
(我写的是util.promisify),它封装了宣传任何函数的能力 .它与其他答案中提出的方法没有太大的不同,但具有作为核心方法的优点,并且不需要额外的依赖性 .
然后你有一个返回原生
Promise
的readFile
方法 .在节点v7.6下,它内置了promises和async:
如何使用:
您可以在Node JS中使用JavaScript本机承诺 .
My Cloud 9代码链接:https://ide.c9.io/adx2803/native-promises-in-node
es6-promisify
将基于回调的函数转换为基于Promise的函数 .参考:https://www.npmjs.com/package/es6-promisify
我不认为@Benjamin的
window.onload
建议会一直有效,因为它不会检测它是否在加载后被调用 . 我被这多次咬过了 . 这是一个应该始终有效的版本:当你有一些函数需要回调并且你希望它们返回一个promise而你可以使用这个函数来进行转换 .
在Node.js 8中,您可以使用此npm模块动态地使用对象方法:
https://www.npmjs.com/package/doasync
它使用 util.promisify 和 Proxies ,以便您的对象保持不变 . Memoization 也是使用WeakMaps完成的 . 这里有些例子:
对象:
功能:
您甚至可以使用原生
call
和apply
来绑定某些上下文:承诺有状态,他们开始等待,并可以解决:
fulfilled 表示计算成功完成 .
rejected 表示计算失败 .
承诺返回函数should never throw,他们应该返回拒绝 . 从promise返回函数中抛出将强制您同时使用
} catch {
和.catch
. 使用promisified API的人不希望承诺投掷 . 如果您不确定JS中的异步API是如何工作的 - 请首先see this answer .1. DOM加载或其他一次性事件:
因此,创建承诺通常意味着指定它们何时结算 - 这意味着它们何时转移到已完成或被拒绝的阶段以指示数据可用(并且可以使用
.then
进行访问) .使用支持
Promise
构造函数的现代promise实现,如本机ES6承诺:然后,您将使用生成的承诺,如下所示:
使用支持延迟的库(我们在这里使用$ q这个例子,但我们稍后也会使用jQuery):
或者使用类似API的jQuery,挂钩一次发生的事件:
2.普通回调:
这些API很常见,因为...回调在JS中很常见 . 让我们来看看
onSuccess
和onFail
的常见情况:使用支持
Promise
构造函数的现代promise实现,如本机ES6承诺:使用支持延迟的库(我们在这里使用jQuery,但我们也使用了上面的$ q):
jQuery还提供了一个
$.Deferred(fn)
表单,它的优点是允许我们编写一个非常接近new Promise(fn)
表单的表达式,如下所示:注意:这里我们利用了jQuery延迟的
resolve
和reject
方法是"detachable";即 . 它们绑定到jQuery.Deferred()的实例 . 并非所有的lib都提供此功能 .3.节点样式回调(“nodeback”):
节点样式回调(nodebacks)具有特定格式,其中回调始终是最后一个参数,其第一个参数是错误 . 我们先来吧手动宣传一个:
至:
使用deferreds,您可以执行以下操作(让我们在此示例中使用Q,尽管Q现在支持新语法which you should prefer):
一般来说,你不应该手动过多地宣传事物,大多数承诺在设计时考虑到Node以及Node 8中的本机承诺的库都有内置的方法来实现节点回传 . 例如
4.具有节点样式回调的整个库:
这里没有黄金法则,你一个接一个地宣传它们 . 但是,一些promise实现允许您批量执行此操作,例如在Bluebird中,将nodeback API转换为promise API非常简单:
或者在 Node 中使用原生承诺:
笔记:
当然,当你在
.then
处理程序中时,你不需要宣传事物 . 从.then
处理程序返回一个promise将解析或拒绝该promise的值 . 从一个.then
处理程序投掷也是很好的做法,并将拒绝承诺 - 这是着名的承诺抛出安全 .在实际的
onload
情况下,您应该使用addEventListener
而不是onX
.callback style 函数总是这样(node.js中的几乎所有函数都是这种样式):
这种风格具有相同的功能:
回调函数由最后一个参数传递 .
回调函数总是接受错误对象作为它的第一个参数 .
所以,您可以编写一个函数来转换具有此样式的函数,如下所示:
为了更简洁,上面的例子使用了ramda.js . Ramda.js是一个优秀的函数式编程库 . 在上面的代码中,我们使用它的 apply (如javascript
function.prototype.apply
)和追加(如javascriptfunction.prototype.push
) . 所以,我们现在可以将回调样式函数转换为promise样式函数:toPromise 和 checkErr 函数由berserk库拥有,它是 ramda.js (由我创建)的函数式编程库 .
希望这个答案对你有用 .
我的
callback
函数的promisify版本是P
函数:P
函数要求回调签名必须为callback(error,result)
.Node.js 8.0.0包含一个新的
util.promisify()
API,它允许将标准Node.js回调样式API包装在一个返回Promise的函数中 .util.promisify()
的示例用法如下所示 .见Improved support for Promises
您可以在ES6中使用 native Promise ,例如处理setTimeout:
在这个例子中,Promise没有理由失败,所以
reject()
永远不会被调用 .Before converting a function as promise In Node.JS
After Converting It
Incase you need to handle multiple request