解决所有延迟问题后执行某些操作

Do something when all deferreds are resolved

本文关键字:执行 操作 问题 延迟 解决      更新时间:2023-09-26

我有以下代码:

loadOpportunities: function () {
    return $.getJSON("/Opportunity/GetAll").pipe(function (result) {
        //do stuff
    });
},
loadTypes: function () {
    return $.getJSON("/OpportunityTypes/GetAll", null, function (result) {
      //do stuff
    });
},
loadView: function () {
    var self = this;
    var deferred = $.Deferred();
    if (!self.viewLoaded) {
        imp2.mainViewModel.loading(true);
        deferred.pipe($.get('/Opportunities/Opportunity/GetView')
        .done(function (data) {
            $('div#opportunity').html(data);
        }));
        deferred.pipe(self.loadTypes);
        deferred.pipe(self.loadOpportunities)
        .done(function () {
            imp2.mainViewModel.loading(false);
        });
    }
    return deferred.resolve();
},

当 loadView 完全完成后,我想做一些事情,包括所有回调。换句话说:我想在 GetView ajax 调用、loadTypes 函数和 loadOpportunities 函数(包括它们的回调)都完成后执行一些代码。

然后,当未完成所有操作时,将触发以下回调函数。我该怎么做?

self.loadView.then(function () {
    //Do something after ALL stuff, including all callbacks is done in loadView
});

我觉得这里可能会对延迟、承诺和管道的使用感到有些困惑。

我认为你想要的是这样的东西(http://jsfiddle.net/JohnMunsch/ghdgD/):

var testObject = {
  loadOpportunities: function () {
    // This is basically saying that we're getting something via AJAX, but we want to take a swipe at changing it
    // before anyone else gets it, so by using pipe we're returning a different promise than the AJAX promise and
    // the value returned from that is what we want others to get.
    return $.ajax({
        url: "/echo/json/",
        data: opportunities,
        type: "POST"
      }).pipe(
        function (result) {
          console.log("[1]", result);
          // Change the result in some way and then return the changed result. Otherwise there's no point in using
          // a pipe() here, a done() would work as well.
          result.opportunities[0].name = "meat packer";
          return result;
        }
      );      
  },
  loadTypes: function () {
    // This example is different from loadOpportunities in that it isn't using a pipe() so what is returned from
    // this function is the same promise that $.ajax() gave us. Any call to .done() just echos back the same
    // promise you gave it.
    return $.ajax({
        url : "/echo/json/",
        data : opportunityTypes,
        type : "POST"
      }).done(
        function (result) {
          console.log("[1]", result);
          // We can do something with the data received here, but outside of this function, anything that tied to
          // the promise from the $.ajax() will see the original data, not any changes we might make here.                    
        }
      );
  },
  loadView: function () {
    // The self = this, scope = this, etc. that you see at the start of functions is only necessary if there are
    // closures below where this might be something else. This code doesn't have that so this line is unneeded.
    //
    // Be careful about cargo-cult programming and just doing something because you do it everywhere else or you
    // see someone else do something. Try to understand why it's there.
    // var self = this;
    if (!this.viewLoaded) {
      console.log("loading");
      var viewPromise = $.ajax({
          url : "/echo/json/",
          data : view,
          type : "POST"
      }).done(
        function (result) {
          console.log("[1]", result);
          // We might take this and dump it in a <div> somewhere.
        }
      );
      var typesPromise = this.loadTypes();
      var opportunitiesPromise = this.loadOpportunities();
      // The following line hands back a single promise (that's what $.when() does) that wraps all three of the
      // other promises and only fires when all three have completed OR when any one of them has failed.
      return $.when(typesPromise, opportunitiesPromise, viewPromise).done(
        function () {
          // Here I've tied a function to the promise as soon as I've created it. But since I'm handing back the
          // promise, I can also tie functions to it later as well, even after the promise has resolved or been
          // rejected.
          console.log("[2]", "All done loading types, views, and opportunities");
        }
      );
    }
    return true;
  }
};
// Note: Unlike with all the steps labeled [1], I don't believe there is a formal ordering for the
// .done()'s attached to the same promise like both [2] and [3]. So it may be possible for those two steps to
// happen [2]/[3] or [3]/[2] although they always happened [2]/[3] in my testing.
$.when(testObject.loadView()).done(
  function () {
    console.log("[3]", "This will only trigger after all the steps in load view have completed.");
  }
);

注意:我更改了 AJAX 调用的样式,但这只是因为我需要在 jsFiddle 中构建一个工作示例。单击上面的链接以查看该链接的实际效果。它可以工作,并按照您的期望订购东西。您可能并不需要您想象的那么多管道,除非您计划在与承诺相关的任何人看到结果之前操纵 AJAX 结果。否则,.done()、.fail() 和 .when() 将处理大多数情况。