简体   繁体   中英

Handle Deferrred with ASYNC AJAX calls

I have a function that looks similar to the following:

function refreshData() {
    service.getSettings().done(function (settings) {
        // DATA 1
        service.getData1(settings).done(function (result) {
            // do something local with result
            // partial resolve 1
        });
        // DATA 2
        var localData = service.getLocalData();
        if (localData.length) {
            service.getData2(settings, localData).done(function (result) {
                // do something local with result
                // partial resolve 2
            });
        } else {
            $('#list').empty();
            // or partial resolve 2
        }
    });
}

What I want to do is create a Deferred object for this function so I know when the data refresh is fully done. I know I could chain them together with $.when but I want the two AJAX calls to run independently and I don't care if one finishes before the other.

I've marked above where I want to each piece to resolve. I'm just not sure how to accomplish this.

My end goal would be a call like this:

refreshData().done(function() {    
    // hide loader
});

how about something like this,

function refreshData() {
    var def1 = $.Deferred();
    var def2 = $.Deferred();

    service.getSettings().done(function (settings) {
        service.getData1(settings).done(function (result) {
            def1.resolve(result);
        });
        var localData = service.getLocalData();
        if (localData.length) {
            service.getData2(settings, localData).done(function (result) {
                def2.resolve(result);
            });
        } else {
            $('#list').empty();
            def2.resolve();
        }
    });    

    // return aggregated promise
    return $.when(def1, def2);
}


refreshData().done(function(r1, r2) {    
     // hide loader
});

Note: untested

The main things you need to do are :

  • to return a composite promise generated by $.when(partial1, partial2)
  • to generate (and return) that promise inside a .then() chained to your outer service.getSettings()

You may also want to make failure of the partials observable, as least for debugging.

function refreshData() {
    return service.getSettings().then(function (settings) {//note `return` and `.then()`
        var partial1, partial2; // declare two promises

        // utility function make error observable - avoids repetition below
        function handleError(err) {
            console.error(err);
        });

        partial1 = service.getData1(settings).done(function (result) {
            //do something local with result
        }).fail(handleError);//make failure of partial1 observable

        var localData = service.getLocalData();//assume this is synchronous
        if (localData.length) {
            partial2 = service.getData2(settings, localData).done(function (result) {
                //do something local with result
            }).fail(handleError);//make failure of partial2 observable
        } else {
            partial2 = $('#list').empty().promise();//sneaky way to generate a resolved promise
        }

        return $.when(partial1, partial2);//as we are inside a `.then()`, the promise generated here is effectively returned by refreshData().
    });
}

see comments in code

Call as follows :

refreshData().done(function() {    
    // hide loader
}).fail(function(err) {
    // indicate failure
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM