承诺链接:在接下来的回调中使用先前承诺的结果

时间:2014-11-13 06:53:43

标签: javascript promise ecmascript-6 ecmascript-harmony

我使用直接的ES6 Promises(使用es6-promise polyfill库),并且遇到了链接的先前承诺的结果问题。

这个问题在Angular / Q的背景下是相同的,但我对答案不满意,并希望看看是否有更好的方法:

How to access result from the previous promise in AngularJS promise chain?

请考虑以下代码段:

Student.find().then(function(student) {
        return HelpRequest.findByStudent(student);
    }, function(error) { //... }
).then(function(helpRequest) {
    // do things with helpRequest...
    // PROBLEM: I still want access to student. How can I get access to it?
});

在链式承诺中,我想使用我在第一个承诺中得到的student对象。但正如所写,这无法访问它。我有几个明显的选择:

  1. 将学生存放在外部范围的变量中(yuck)
  2. 我实际上并不知道这是如何运作的,但另一个问题中的解决方案建议我可以thenHelpRequest.findByStudent()的结果致电Promise.resolve Student.find().then调用中的合并结果。不过,我认为以下的实施工作不会起作用。

    Student.find().then(function(student) {
            var data = {student: student};
            HelpRequest.findByStudent(student).then(function(helpRequest) {
                data.helpRequest = helpRequest;
            });
            // PROBLEM: if HelpRequest.findByStudent(student) is asynchronous, how 
            // does this get the data before returning?
            return data; 
        }, function(error) { //... }
    ).then(function(helpRequest) {
        // do things with helpRequest and student
    });
    
  3. 我绝对不想处理嵌套在helpRequest方法中的Student.find(),因为这会破坏链接Promise的目的;即使第二个例子可以处于可用状态,它仍然感觉像是一个黑客。

    有没有更好的方法来实现这一点,而无需引入全局状态或嵌套到我的代码中?例如,有没有办法在多个值上调用Promise.resolve(),其中一些可能是承诺而另一些则不是?

    我很好奇,希望我有其他选择/可以理解如何在不引入嵌套或状态的情况下正确地完成这项工作!

1 个答案:

答案 0 :(得分:5)

在我看来,承诺的禅就是要弄清楚他们真的只是异步价值。如果您开始使用它们,这些问题在许多情况下会变得更简单。它不是一颗银弹,但确实有帮助:

在ES5中:

var student = Student.find();
var helpRequest = student.then(HelpRequest.findByStudent);
Promise.all([student, helpRequest]).then(function(results){
    var student = results[0];
    var helpRequest = results[1];
    // access both here
});

在ES6中,具有以下所有功能:

var student = Student.find();
var helpRequest = student.then(HelpRequest.findByStudent);
Promise.all([student, helpRequest]).then(([student, helpRequest]) => {
    // access both here
});

在另一个更富有的承诺库(蓝鸟):

var student = Student.find();
var helpRequest = student.then(HelpRequest.findByStudent);
Promise.join(student, helpRequest, function(student, helpRequest){
    // access both here
});