Promise chain: use the result of the previous promise in the next callback

I am using straight ES6 Promises (with es6-prom polyfill library) and I am having problem accessing the results of previous Promises in the chain.

This problem is identical in the Angular / Q context, but I'm not happy with the answer and want to see if there is a better way:

How do I get the result from the previous promise in the AngularJS promise chain?

Consider the code snippet below:

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

      

In a pivot promise, I want to use the object student

I received in the first promise. But as written, this cannot access it. I have several obvious options:

  • store the student in a variable in the outer scope (yuck)
  • I don't really know how this would work, but the solutions in the other question assume that I can call the then

    result HelpRequest.findByStudent()

    and the Promise.resolve

    combined result within the Student.find().then

    call. The implementation below will not work I guess.

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

I absolutely don't want to helpRequest

nest the processing inside the method Student.find()

, as that defeats the purpose of chaining Promises; and even though the second example can be processed in a usable state, it still looks like a hack.

Is there a better way to achieve this without introducing global state or nesting it into my code? For example, is there a way to call Promise.resolve()

for multiple values, some of which may be Promises and some of which are not?

I'm curious, hopefully I have alternatives / can figure out how to do this correctly without introducing nesting or state!

+3


source to share


1 answer


In my opinion, Zen promises are all about understanding that they are really just async values. If you start using them as such, in many cases these problems will become easier. It's not a silver bullet, but it does help:

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

      

In ES6 with all its features:



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

      

In another rich promise library (bluebird):

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

      

+5


source







All Articles