我将代码重构为承诺,并构建了一个奇妙的长而平坦的承诺链,由多个.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?
    });
}

当前回答

当使用bluebird时,你可以使用.bind方法来共享承诺链中的变量:

somethingAsync().bind({})
.spread(function (aValue, bValue) {
    this.aValue = aValue;
    this.bValue = bValue;
    return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
    return this.aValue + this.bValue + cValue;
});

请点击此链接了解更多信息:

http://bluebirdjs.com/docs/api/promise.bind.html

其他回答

可变上下文状态

简单的(但不优雅且容易出错)解决方案是使用更高范围的变量(链中的所有回调都可以访问),并在获得结果值时将结果值写入它们:

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

人们也可以使用一个(初始为空的)对象来代替许多变量,结果将作为动态创建的属性存储在对象上。

这个解决方案有几个缺点:

Mutable state is ugly, and global variables are evil. This pattern doesn't work across function boundaries, modularising the functions is harder as their declarations must not leave the shared scope The scope of the variables does not prevent to access them before they are initialized. This is especially likely for complex promise constructions (loops, branching, excptions) where race conditions might happen. Passing state explicitly, a declarative design that promises encourage, forces a cleaner coding style which can prevent this. One must choose the scope for those shared variables correctly. It needs to be local to the executed function to prevent race conditions between multiple parallel invocations, as would be the case if, for example, state was stored on an instance.

Bluebird库鼓励使用传递的对象,使用bind()方法将上下文对象分配给承诺链。每个回调函数都可以通过不可用的this关键字访问它。虽然对象属性比变量更容易出现无法检测到的错别字,但该模式相当聪明:

function getExample() {
    return promiseA(…)
    .bind({}) // Bluebird only!
    .then(function(resultA) {
        this.resultA = resultA;
        // some processing
        return promiseB(…);
    }).then(function(resultB) {
        // more processing
        return // something using both this.resultA and resultB
    }).bind(); // don't forget to unbind the object if you don't want the
               // caller to access it
}

这种方法可以很容易地在不支持.bind的promise库中模拟(尽管以一种更详细的方式,并且不能在表达式中使用):

function getExample() {
    var ctx = {};
    return promiseA(…)
    .then(function(resultA) {
        this.resultA = resultA;
        // some processing
        return promiseB(…);
    }.bind(ctx)).then(function(resultB) {
        // more processing
        return // something using both this.resultA and resultB
    }.bind(ctx));
}

当使用bluebird时,你可以使用.bind方法来共享承诺链中的变量:

somethingAsync().bind({})
.spread(function (aValue, bValue) {
    this.aValue = aValue;
    this.bValue = bValue;
    return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
    return this.aValue + this.bValue + cValue;
});

请点击此链接了解更多信息:

http://bluebirdjs.com/docs/api/promise.bind.html

Node 7.4现在支持带有和谐标志的async/await调用。

试试这个:

async function getExample(){

  let response = await returnPromise();

  let response2 = await returnPromise2();

  console.log(response, response2)

}

getExample()

然后运行文件:

node——harmony-async-await getExample.js

尽可能的简单!

我不打算在我自己的代码中使用这种模式,因为我不太喜欢使用全局变量。然而,在紧要关头它还是有用的。

用户是一个承诺的猫鼬模型。

var globalVar = '';

User.findAsync({}).then(function(users){
  globalVar = users;
}).then(function(){
  console.log(globalVar);
});

另一个答案,使用babel节点版本<6

使用async - await

NPM install -g babel@5.6.14

example.js:

async function getExample(){

  let response = await returnPromise();

  let response2 = await returnPromise2();

  console.log(response, response2)

}

getExample()

然后,运行babel-node example.js,瞧!