1

I have a code that looks something like this

class foo {
    constructor() {

        // calling a, b, c synchronously
        a().then(
            function(response) {
                b().then(
                    function(response) {
                        c();
                    }, function(error) {
                        // pass
                    }
                );
            }, function(error) {
                // pass
            }
        );
    }

    a() {
        return new Promise(function(fullfill, reject) {

            // x is any function that returns a promise, making the
            // implementation of this function "a" asynchronous
            x().then(
                function(response) {
                    fullfill(response);
                }, function(error) {
                    reject(error);
                }
            );

        });
    }

    b() {
        return new Promise(function(fullfill, reject) {

            // x is any function that returns a promise, making the
            // implementation of this function "b" asynchronous
            x().then(
                function(response) {
                    fullfill(response);
                }, function(error) {
                    reject(error);
                }
            );

        });
    }

    c() {
        // do something
    }

}

Basically, I have two functions a and b which are both asynchronous. These functions are asynchronous because they both call some function x which returns a promise (in my case, it is a query to a database).

I need to call a, followed by b followed by c but sequentially. One way of doing so is what I have implemented in the code above, but it results in nasty nested promise responses.

Is there any other way that I can achieve this same result, without using the following syntax (because if this is the only possible solution, then I might as well not use it at all).

6
  • 1
    use promise chaining stackoverflow.com/questions/34696696/… Commented Jan 17, 2017 at 11:27
  • @atmd Yes. a, b and c are functions that I have written. But they all make queries to a database and these queries are asynchronous. And I have no control over these queries. Commented Jan 17, 2017 at 11:29
  • What @m14 said, just do a().then(b).then(c);. Commented Jan 17, 2017 at 11:36
  • 1
    If x() has a .then() then it's already a promise. DO NOT create a promise yourself in this case, just do a() {return x()}. That's all. Only if x() does not return a promise (don't have a .then()) should you create a promise yourself. Commented Jan 17, 2017 at 11:52
  • 1
    BTW, synchronously !== sequentially. You cannot synchronise an asynchronous function; but you can call several asynchronous functions in sequence… Commented Jan 17, 2017 at 14:05

2 Answers 2

2

Use promise chaining as shown below:

a().then(resA => {
    // resA is response of function a()
    // Do whatever you want with resA here
    // and then return promise of function b()

    return b();
})
.then(resB => {
    // resB is response of function b()
    // Do whatever you want with resA here
    // and then return promise of function c()

    return c();
})
.then(resC => {
    // resC is response of function c()
    // Do whatever you want with resC here
})
.catch(err => {
    // Handle any reject/error of functions a, b or c
});

If you want to carry the response of function a and b till the end then you can do the chaining as follows:

a().then(resA => {
    // resA is response of function a()
    // Do whatever you want with resA here
    // and then return promise of function b()

    return b().then(resB => { resA: resA, resB: resB });
})
.then(res => {
    // res is a object with rsponse of function a() & b()
    // res.resA is response of function a()
    // res.resB is response of function b()
    // Do whatever you want to with the responses here
    // then return promise of function c()

    return c().then(resC, { resA: res.resA, resB: res.resB, resC: resC });
})
.then(resC => {
    // res is a object with rsponse of function a(), b() & c()
    // res.resA is response of function a()
    // res.resB is response of function b()
    // res.resC is response of function c()
    // Do whatever you want to with the responses
})
.catch(err => {
    // Handle any reject/error of functions a, b or c
});

The above code is elaborate for demo/explanation. It can be reduced with ES6 as shown below

a().then(resA => {
    // resA is response of function a()
    // Do whatever you want with resA here
    // and then return promise of function b()

    return b().then(resB => { resA, resB });
})
.then(res => {
    // res is a object with rsponse of function a() & b()
    // res.resA is response of function a()
    // res.resB is response of function b()
    // Do whatever you want to with the responses here
    // then return promise of function c()

    return c().then(resC, Object,assign(res, { resC }));
})
.then(resC => {
    // res is a object with rsponse of function a(), b() & c()
    // res.resA is response of function a()
    // res.resB is response of function b()
    // res.resC is response of function c()
    // Do whatever you want to with the responses
})
.catch(err => {
    // Handle any reject/error of functions a, b or c
});

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

0

Let seq = [f1,f2,...,fn] be a sequence of zero-argument promise returning functions. Build a promise p that will execute them sequentially with fi invoked after f{i-1}.

var p = seq.reduce( (p_acc,f) => p_acc.then( ()=>f() ) )

Then you probably want to do

p.catch(...)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.