Promise waterfall

12,652

You've got a promise anti pattern happening. You can return promises from promises to avoid nesting the promises like you've done.

promiseOne()
    .then(() => promiseTwo())
    .then(() => promiseThree())
    .then(() => promiseFour());

By the way Node supports the built in Promise constructor.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

const promise = new Promise((resolve, reject) => {
    // do something and then resolve
    resolve();
})
promise().then(() => { ... });
Share:
12,652
ChrisRich
Author by

ChrisRich

Sydney based full stack software developer

Updated on August 13, 2022

Comments

  • ChrisRich
    ChrisRich almost 2 years

    I'm an API developer and typically write end-points requiring passing a result from one async call to another async call aka async waterfall.

    I usually do this the following way using promises:

    task1()
    
    .then(result1){
    
        task2(result1)
    
        .then(result2){
    
            task3(result2)
    
            .then(result3){
                // API response
            })
    
            .catch(function(err){
                // Task 3 handle err
            })
        })
    
        .catch(function(err){
            // Task 2 handle err
        })
    })
    
    .catch(function(err){
        // Task 1 handle err
    })
    

    It's obvious that not much has been gained over using callbacks. Instead of "callback hell" I now got "promise hell".

    I have looked at npm bluebird but it does not seem that waterfall promises are supported.

    Sometimes I would use async and wrap tasks that return a promise:

    const tasks = [
    
        job1: function(cb){
    
            task1()
    
            .then(function(result){
                cb(null, result);
            })
    
            .catch(function(err){
                cb(err);
            })  
        },
    
        job2: function(cb, result1){
    
            task2(result1)
    
            .then(function(result){
                cb(null, result);
            })
    
            .catch(function(err){
                cb(err);
            })  
        },
    
        job3: function(cb, result2){
    
            task3(result2)
    
            .then(function(result){
                cb(null, result);
            })
    
            .catch(function(err){
                cb(err);
            })  
        }
    ]
    
    async.series(tasks, function(err, results){
    
        if(err){
            // handle error
        }
    
        // API callback
    });
    

    But this is also pretty useless. And if you're thinking about Promise.all that wont work since the result from one tasks is not passed on to the next.

    What's the better approach?