如何在.then()链中访问先前的承诺结果?

我已经将我的代码重组为承诺,并构建了一个美妙的长平诺言链 ,由多个.then()回调组成。 最后,我想返回一些复合值,并需要访问多个中间承诺结果 。 但是,从序列中间的分辨率值不在最后一次回调的范围内,我如何访问它们?

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?
    });
}

打破这个链条

当你需要访问链条中的中间值时,你应该将链条拆分成你需要的单件。 而不是附加一个回调,并以某种方式多次尝试使用其参数,将多个回调附加到相同的承诺 - 无论您需要结果值。 不要忘记,一个承诺只代表(代理)未来的价值! 接下来从线性链中的另一个承诺中获取一个承诺,使用库所提供的承诺组合器来构建结果值。

这将导致一个非常简单的控制流程,清晰的功能组成,因此易于模块化。

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调用将被许多诺言库(Q,Bluebird,when,...)提供的漂亮的辅助方法取代: .spread(function(resultA, resultB) { …

Bluebird还具有一个专用的join函数,用一个更简单(更高效)的构造来代替Promise.all + spread组合:

…
return Promise.join(a, b, function(resultA, resultB) { … });

ECMAScript和谐

当然,这个问题也得到了语言设计师的认可。 他们做了很多工作,异步功能建议最终成功实现

ECMAScript 8

你并不需要一个单一的then调用或回调函数更多,比如在异步函数(即返回时,被称为承诺),你可以简单地等待承诺以直接解决。 它还具有任意的控制结构,如条件,循环和try-catch-clause,但为了方便起见,我们在这里不需要它们:

async function getExample() {
    var resultA = await promiseA(…);
    // some processing
    var resultB = await promiseB(…);
    // more processing
    return // something using both resultA and resultB
}

ECMAScript 6

在等待ES8时,我们已经使用了非常类似的语法。 ES6带有生成器函数,它允许在任意放置的yield关键字中分割执行。 这些切片可以独立运行,甚至是异步运行 - 这就是我们在运行下一步之前等待承诺解决方案时所做的。

有专用的库(如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中起作用,而且一些浏览器(或其开发版本)确实比较早地支持生成器语法。

ECMAScript 5

但是,如果您希望/需要向后兼容,则不能在没有转译器的情况下使用这些转换器。 目前的工具支持发电机功能和异步功能,例如参见发电机和异步功能的Babel文档。

然后,还有许多其他编译器对JS语言,这些语言致力于缓解异步编程。 它们通常使用类似于await的语法(例如Iced CoffeeScript),但也有其他类似于Haskell的do -notation(例如LatteJs,monadic,PureScript或LispyScript)。


同步检查

为变量分配promise-for-later-needed-values,然后通过同步检查获取它们的值。 该示例使用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();
    });
}
链接地址: http://www.djcxy.com/p/9445.html

上一篇: How do I access previous promise results in a .then() chain?

下一篇: What is the explicit promise construction antipattern and how do I avoid it?