ironstein
ironstein

Reputation: 547

Javascript - call two asynchronous functions sequentially

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).

Upvotes: 1

Views: 3581

Answers (2)

J Adrian Zimmer
J Adrian Zimmer

Reputation: 7

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(...)

Upvotes: 0

Santanu Biswas
Santanu Biswas

Reputation: 4787

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.

Upvotes: 2

Related Questions