我已经将我的代码重组为Promise ,并构建了一个精彩的长期扁平 Promise 链,其中包括多个.then()
回调。最后,我想返回一些复合值,并且需要访问多个中间的 Promise 结果。但是,序列中间的分辨率值不在上次回调的范围内,如何访问它们?
function getExample() {
return promiseA(…).then(function(resultA) {
// Some processing
return promiseB(…);
}).then(function(resultB) {
// More processing
return // How do I gain access to resultA here?
});
}
当您需要访问链中的中间值时,应将链分成所需的单个部分。不必附加一个回调并以某种方式尝试多次使用其参数,而是将多个回调附加到同一 promise - 无论何时需要结果值。不要忘记,承诺只是代表(代理)未来的价值!除了从线性链中的另一个承诺中推导一个承诺之外,还可以使用库提供给您的 promise 组合器来构建结果值。
这将导致非常简单的控制流程,清晰的功能组合,因此易于模块化。
function getExample() {
var a = promiseA(…);
var b = a.then(function(resultA) {
// some processing
return promiseB(…);
});
return Promise.all([a, b]).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
Promise.all
之后的回调中消除参数破坏,所有这些仅在 ES6 中才可用,在 ES5 中, then
调用将由许多 promise 库(Q , Bluebird , when ,…)提供的漂亮的助手方法代替.spread(function(resultA, resultB) { …
。
蓝鸟还具有专用的join
功能,可以用更简单(更有效)的结构Promise.all
+ spread
…
return Promise.join(a, b, function(resultA, resultB) { … });
当然,语言设计者也意识到了这个问题。他们做了很多工作,异步功能提案最终使它成为了
您不再需要单个then
调用或回调的函数,因为在异步函数(被调用时返回一个 promise)中,您只需等待 promise 直接解析即可。它还具有诸如条件,循环和 try-catch-clauses 之类的任意控制结构,但是为了方便起见,我们在这里不需要它们:
async function getExample() {
var resultA = await promiseA(…);
// some processing
var resultB = await promiseB(…);
// more processing
return // something using both resultA and resultB
}
在等待 ES8 时,我们已经使用了非常相似的语法。 ES6 带有生成器函数,该函数允许在任意放置的yield
关键字处将执行分段。这些切片可以相互独立,甚至异步地运行 - 这就是我们要在执行下一步之前等待 promise 解析时所要做的。
有专用的库(例如co或task.js ),但是还有许多Promise 库具有辅助函数(Q , Bluebird , when …),当您为它们提供生成器函数时,它们会为您执行异步逐步执行产生希望。
var getExample = Promise.coroutine(function* () {
// ^^^^^^^^^^^^^^^^^ Bluebird syntax
var resultA = yield promiseA(…);
// some processing
var resultB = yield promiseB(…);
// more processing
return // something using both resultA and resultB
});
从 4.0 版开始,它确实在 Node.js 中起作用,而且一些浏览器(或其开发版本)相对较早地支持生成器语法。
但是,如果您希望 / 需要向后兼容,那么在没有编译器的情况下不能使用它们。当前工具支持生成器功能和异步功能,例如,请参见 Babel 有关生成器和异步功能的文档。
然后,还有许多其他专用于 JS 的可编译为 JS 的语言致力于简化异步编程。他们通常使用类似语法await
(例如冰的 CoffeeScript ),但也有其他人配备了哈斯克尔样do
-notation(如LatteJs ,一元, PureScript或LispyScript )。
为变量分配可满足的承诺值,然后通过同步检查获取其值。该示例使用 bluebird 的.value()
方法,但是许多库提供了类似的方法。
function getExample() {
var a = promiseA(…);
return a.then(function() {
// some processing
return promiseB(…);
}).then(function(resultB) {
// a is guaranteed to be fulfilled here so we can just retrieve its
// value synchronously
var aValue = a.value();
});
}
您可以将其用于任意多个值:
function getExample() {
var a = promiseA(…);
var b = a.then(function() {
return promiseB(…)
});
var c = b.then(function() {
return promiseC(…);
});
var d = c.then(function() {
return promiseD(…);
});
return d.then(function() {
return a.value() + b.value() + c.value() + d.value();
});
}