在所有延期解决后执行某些操作 [英] Do something when all deferreds are resolved

查看:53
本文介绍了在所有延期解决后执行某些操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

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函数(包括它们的回调)都完成时执行一些代码。

I want to do something when loadView has finished completely, including all callbacks. In other words: I want to execute some code when the GetView ajax call, the loadTypes function and the loadOpportunities function including their callbacks are all done.

以下再回调函数当并非全部完成时会发生火灾。我该怎么做?

The following then callback function fires when not all is completed. How can I do this?

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


推荐答案

我觉得使用时可能会有些混乱延迟,承诺和管道在这里。

I sense there may be a little confusion on the use of deferred, promises, and pipes here.

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

I think what you want is something like this (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中的示例。点击上面的链接,看看那里的情况。它可以工作,并按照您的预期订购。你可能不需要像你想象的那样管道,除非你打算在任何与promise相关的人看到结果之前操纵AJAX结果。否则,.done(),. fail()和.when()将处理大多数情况。

Note: I changed the style of your AJAX calls but that was just because I needed to build a working example in jsFiddle. Click on the link above to see this in action over there. It works and it orders things as you expect. You probably don't need pipe as much as you think unless you plan to manipulate the AJAX results before anyone tied to the promise sees the results. Otherwise, .done(), .fail(), and .when() will handle most situations.

这篇关于在所有延期解决后执行某些操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆