承诺链接:在next-then回调中使用上一个承诺的结果

Promise chaining: Use result from previous promise in next then callback

本文关键字:一个承诺 结果 链接 next-then 回调 承诺      更新时间:2023-09-26

我使用的是直接的ES6-Promises(带有ES6-promise polyfill库),在访问链接中的先前promise的结果时遇到了问题。

这个问题在Angular/Q的上下文中是相同的,但我对答案不满意,想看看是否有更好的方法:

如何访问AngularJS承诺链中上一个承诺的结果?

考虑下面的代码片段:

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

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

  1. 将学生存储在外部范围的变量中(当然)
  2. 事实上,我不知道这将如何工作,但另一个问题中的解决方案建议我可以对HelpRequest.findByStudent()的结果调用then,并对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
    });
    

我绝对不想处理嵌套在Student.find()方法中的helpRequest,因为这违背了链接Promises的目的;即使第二个例子可以进入可用状态,它仍然感觉像是黑客。

有没有更好的方法可以实现这一点,而不必在我的代码中引入全局状态或嵌套?例如,有没有一种方法可以对多个值调用Promise.resolve(),其中一些值可能是promise,而另一些值不是?

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

在我看来,promise的zen就是要弄清楚它们实际上只是异步值。如果你开始这样使用它们,这些问题在很多情况下会变得更简单。这不是银弹,但它确实有帮助:

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