ObiHill
ObiHill

Reputation: 11876

Chaining JavaScript Promises that include nested AJAX calls

I'm looking to replace some of my existing code with JavaScript Promises and I just want to confirm that I'm not doing it wrong (or maybe there are better ways). I'm using the es6-promise library.

What I have are three functions that I've updated to use JavaScript Promises (what was previously a nested, callback-ey mess). The functions are actually supposed to have dual modes i.e. I can use them like regular functions and have them return a result, or I could chain them together.

function func_1()
{
    return new Promise(function(resolve, reject){
        if(condition)
        {
            resolve('1');
        }
        else
        {
            console.log('start');
            resolve(ajaxRequest(url));
        }
    });
}

function func_2(data)
{
    return new Promise(function(resolve, reject){
        if(condition)
        {
            resolve('2');
        }
        else
        {
            console.log(data.response);
            resolve(ajaxRequest(url));
        }
    });
}

function func_3(data)
{
    return new Promise(function(resolve, reject){
        if(condition)
        {
            resolve('3');
        }
        else
        {
            console.log(data.response);
            resolve(ajaxRequest(url));
        }
    });
}

func_1().then(func_2).then(func_3).then(function(data){});

The if is to check whether data is cached in localStorage/sessionStorage, and if so the function just returns the result. However, in circumstances where I am unsure if the values have been cached (e.g. first run of the script), then I plan to chain them and then have each subsequent function persist the result from its preceeding one to localStorage/sessionStorage (hence the promise chain on the last line). The final then gives me an opportunity to persist the data from func_3.

Based on the tests I have run, everything seems to be working ok, but I was just wondering if this was the best way of doing this? And how do I handle the AJAX errors that could happen on one or more of the 3 listed functions?

Note: My AjaxRequest function also uses the same Promise mechanism and 'resolves' a full XHR on success, and 'rejects' the same full XHR on failure/error.

EDIT

After a tip from @Bergi, I've updated the code to look like this (and it works just as well):

function func_1()
{
    if(condition)
    {
        return Promise.resolve('1');
    }
    else
    {
        console.log('start');
        return ajaxRequest(url);
    }
}

function func_2(data)
{
    if(condition)
    {
        return Promise.resolve('2');
    }
    else
    {
        console.log(data.response);
        return ajaxRequest(url);
    }
}

function func_3(data)
{
    if(condition)
    {
        return Promise.resolve('3');
    }
    else
    {
        console.log(data.response);
        return ajaxRequest(url);
    }
}

func_1().then(func_2).then(func_3).then(function(data){})['catch'](function(err){console.log(err)});

Upvotes: 1

Views: 1098

Answers (1)

Bergi
Bergi

Reputation: 664297

everything seems to be working ok, but I was just wondering if this was the best way of doing this?

You should never really need to use the Promise constructor except on the lowest level (i.e. when promisifying that ajax request). Your functions should simply be written like this:

function func_1() {
    if (condition) {
        return Promise.resolve('1');
    } else {
        console.log('start');
        retrun ajaxRequest(url);
    }
}

Strictly speaking, the func_2 and func_3 might even do return '2', the then method for which they are used as callbacks can cope with that. Of course it is cleaner to always return a promise object.

And how do I handle the AJAX errors that could happen on one or more of the 3 listed functions?

Pass a second function to then, or use catch. This callback will get called when the promise is rejected, and should handle the exception.

Upvotes: 3

Related Questions