Leandro Gamarra
Leandro Gamarra

Reputation: 151

Is it possible to queue in succesion an array of functions that return promises?

Have the next example:

function exec()
{
    var dfd = $.Deferred();

    asyncStuff().then(
    function(res)
    {
        if(res)
        {
            dfd.resolve(true);
        }
        else
        {
            dfd.resolve(false);
        }
    });

 return dfd.promise();
}

var promise_arr = [];
promise_arr.push( exec() );
promise_arr.push( exec() );
promise_arr.push( exec() );
promise_arr.push( exec() );

Promise.all( promise_arr ).then(
function(res)
{
    console.log("finished!");
});

So the functions inside the array are executed almost simoultaneously. This is not good. One must be called only after another finishes in sequence. Is there a way to queue them?

EDIT:

For it to work I had to call an anonymous function inside the for loop, and I took the adventage to stop Its execution whether my promises returned a correct answer. That anonymous function works as a promise factory, check out: https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html

Also, when I push the functions, I had to remove the braces for them to stop executing on pushing them inside the array.

function Exec()
{
    var dfd = $.Deferred();
    
    setTimeout(
    function()
    { 
        console.log("executing OK"); 
        var res_obj = {};
        res_obj.res_value = true;
        dfd.resolve(res_obj);
    }, 1000);
    
    return dfd.promise();
}

function ExecNO()
{
    var dfd = $.Deferred();
    
    setTimeout(
    function()
    { 
        console.log("Executing ERROR"); 
        var res_obj = {};
        res_obj.res_value = false;
        res_obj.res_error = "Ima error func";
        dfd.resolve(res_obj);
    }, 1000);
    
    return dfd.promise();
}

function ExecSincroProcess( promise_arr )
{
    var res_obj = {};
    res_obj.res_value = true;

    var result = Promise.resolve(res_obj);

    promise_arr.forEach(
        function (promiseFunction) 
        {
            result = 
            result.then(
            function(res)
            {
                if (res.res_value)
                {
                    return promiseFunction();
                }
                else
                {
                    return res;
                }
            });
        });

        result.then(
    function(res)
    {
        console.log(res.res_error);
        console.log("finished!");
    });
}

function ExecAll()
{
    var pr_Arr = [];
    pr_Arr.push(Exec);
    pr_Arr.push(Exec);
    pr_Arr.push(ExecNO);
    pr_Arr.push(Exec);
    pr_Arr.push(Exec);
    
    ExecSincroProcess(pr_Arr);
}

Upvotes: 1

Views: 116

Answers (1)

Mackers
Mackers

Reputation: 1050

There is a way to queue promises. The way I have queued promises in the past is to loop through the array an chain them together with .then clauses:

ex.

let promiseChain = Promise.resolve()
promiseFunctionArray.forEach(promiseFunction => {
    promiseChain = promiseChain.then(promiseFunction)
})

promiseChain.then(() => {/* do what you want to with the results */})

So your case could look like this:

function exec()
{
    var dfd = $.Deferred();

    asyncStuff().then(
    function(res)
    {
        if(res)
        {
            dfd.resolve(true);
        }
        else
        {
            dfd.resolve(false);
        }
    });

 return dfd.promise();
}

var promise_arr = [];
promise_arr.push(exec);
promise_arr.push(exec);
promise_arr.push(exec);
promise_arr.push(exec);

var promiseChain = Promise.resolve()
promise_arr.forEach(promiseFunction => {
    promiseChain = promiseChain.then(promiseFunction)
})

promiseChain.then(
function(res)
{
    console.log("finished!");
});

Upvotes: 2

Related Questions