Deferred Promise - Run Functions One by One after each completes

此生再无相见时 提交于 2019-12-08 05:15:50

问题


I have 3 functions that make aync calls to backend systems : fnOne, fnTwo, fnThree. I know I am not doing it correctly, but cannot figure out the right way.

I am starting off by trying to call them one by after each completes:

However, fnOne already has a deferred object inside of it and when that is resolved it is resolving my promise.

$.when(oController._fnOne()).done(function(){
    console.log("fn one complete");
});

functions

_fnOne: function(){

    var oController = this;

 //when the deferred is done in _checkInstanceStatus, it is resolving the above, rather than the pDeferred in this function resolving the above.
$.when(oController._checkInstanceStatus(oParams)).done(function(oStatusData) {
        //does some stuff 
        return $.Deferred(function() {
            var pDeferred = this;
            //does a call for data and upon success i will resolve ..
            pDeferred.resolve();
        });
    });
}

other function

_checkInstanceStatus: function(oParams){
            return $.Deferred(function() {
                var pDeffered = this;
                //does a call for data and upon success i will resolve...
                pDeffered.resolve(data);

                });
            });
        },

Then the plan is to try and chain them, so they run one by one, like so:

$.when(oController._fnOne())
.then(oController._fnTwo())
.then(oController._fnThree())
.done(function(){
    console.log("all complete!");
});

回答1:


A couple of things:

  1. There's no need to use $.when if you're passing it a single Deferred.

  2. fnOne (and presumably the others) needs to return a promise/Deferred so you know when it completes. Since it's using _checkInstanceStatus, which returns a Deferred, it can do that by using then:

So fnOne might look like this:

fnOne: function() {
    var oController = this;
    return oController.__checkInstanceStatus(oParams).then(function(oStatusData) {
        var pDeferred = $.Deferred();
        callAmazon(function() {
            if (/*successful*/) {
                pDeferred.resolve();
            } else {
                pDeferred.reject();
            }
        });
        return pDeferred.promise(); // Or just the Deferred if you like, but
                                    // normally you want to share promises, not
                                    // Deferred objects
    });
}

Notice how it returns the result of calling then, which is a promise created by calling then. That promise will resolve based on the promise you're returning from the then handler.

You'd follow the same pattern with the other functions.

To chain them one after another, you'd do this:

oController._fnOne()
.then(oController._fnTwo)        // Notice no () on that, we're passing the
.then(oController._fnThree)      // function in, not calling it. Same on this line.
.then(function() {
    console.log("all complete!");
})
.catch(function(error) {
    // Do something about the error
});

(I'm assuming _fnOne and fnOne are the same function.)

I'm assuming a relatively recent version of jQuery that has Promises support in Deferreds.


Side note: I'd switch to using native Promises (with a polyfill if necessary to support old browsers) rather than using jQuery's Deferred, which has...well, it has a lot of history and the API has gotten cumbersome. :-)

With native promises:

fnOne: function() {
    var oController = this;
    return oController.__checkInstanceStatus(oParams).then(function(oStatusData) {
        return new Promise(function(resolve, reject) {
            callAmazon(function() {
                if (/*successful*/) {
                    resolve();
                } else {
                    reject();
                }
            });
        });
    });
}

Usage is the same (because I used Promise APIs that have been added to Deferred in the first example).




回答2:


It's quite difficult to understand your function. So I have make it simple to define 3 new func with 3 different way so that you can understand jquery deferred easier.

var funcOne = function() {
  var defer = $.Deferred();
  $.ajax('/echo/json')
    .then(function(data) {
      console.log('func1', data);
      return defer.resolve(data);
    });
  return defer;
}

var funcTwo = function() {
  console.log('begin call func 2');
  return $.ajax('/echo/json')
    .then(function(data) {
      console.log('func2', data);
      return $.Deferred().resolve(data);
    });
}

var funcThree = $.ajax('/echo/json');

funcOne()
  .then(funcTwo)
  .then(funcThree)
  .then(function(data) {
    console.log('finally got func 3 data', data)
  });

jsfiddle link: https://jsfiddle.net/zmjLaznn/



来源:https://stackoverflow.com/questions/43784439/deferred-promise-run-functions-one-by-one-after-each-completes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!