如何链接方法才能在结束时获得结果?

时间:2016-04-07 12:20:35

标签: javascript jquery jquery-deferred

我有一个简单的服务方法,收集了几个.get(),我在"打印"上遇到了一些麻烦。从那时起,我只有一部分结果。

我正在做的是:

var service = function() {
  var players = []; // will hold 100 objects

  var getMembers = function(id) {
    $.get(url, function(data) {
      for(i=0; i<data.length; i++) {
        var p = data[i];
        // get more info for this member
        getMemberDetails(p.member_id);
        // put the current data into the players
        players.push(p);
      }
    });

    calculateAndPrint();
  };

  var getMemberDetails = function(id) {
    $.get(url, function(data) {
      var result = $.grep(players, function(e){ return e.member_id == id; });
      if (result.length == 0) { /* not found */ } 
      else if (result.length == 1) {
        // push new data to player object
        result[0].details = data;
      }
    });
  };

  var calculateAndPrint = function() {
    for(i=0; i<players.length; i++) {
      var p = players[i];
      console.log(p);
    }
  };
})();

这不起作用,因为当我到达calculateAndPrint时,details甚至还没有设计......

所以我尝试了$.Deferred(),我唯一的问题是,如果我推迟getMemberDetails方法,那个电话已经包含了一个deffer call(.get())和I&I #39;回到同一个问题......

在完成所有100次调用后,仅运行calculateAndPrint的最佳选择是什么?

这似乎很容易,但我只是空白:/

2 个答案:

答案 0 :(得分:3)

如果你使用promises,这应该很容易:

var service = function() {
  var getMembers = function(id) {
      return Promise.when($.get("some service url"))
          .then(function (data) {
              return Promise.all(data.map(getMemberDetails));
          });
  };

  var getMemberDetails = function(player) {
      return Promise.when($.get("some service Url?id=" + player.member_id));
  };

  var calculateAndPrint = function(players) {
      players.forEach(function (player) {
          console.log(player);
      });
  };

  return {
      getMembers: getMembers,
      calculateAndPrint: calculateAndPrint
  };
})();

service.getMembers().then(function (players) {
    service.calculateAndPrint(players);
});

答案 1 :(得分:-1)

你可以为你制作的每个ajax调用创建一个延迟对象$.deferred。然后等待($.when)在运行calculateAndPrint()方法之前完成所有延期作业。

工作原理:

  • 为每个ajax调用创建一个延迟对象$.deferred&amp;返回promise对象.promise()
  • 取决于ajax调用是否成功,请使用响应数据.resolve(responseData)解析或拒绝错误数据.reject(errorData)
  • 通过从步骤1返回的promise对象监视所有ajax调用,并在完成时调用calculateAndPrint()方法。
  • 对于任意ajax调用,上述大多数逻辑保持不变,除了那些在for循环中调用,并且每个延迟调用都被推送到deferredCalls数组。

注意:我建议你在进行ajax调用时显示一些loader / spinner图像,因为你不会立即得到响应&amp;让用户了解后台操作总是很好的用户体验标志。

JS CODE:

/* utils */
var $ul = $('ul');

function msg(text) {
  $ul.append('<li>' + text + '</li>'); 
}

/* functions */
function asyncThing1() {
  var dfd = $.Deferred();
  setTimeout(function() {
    msg('asyncThing1 seems to be done...');
    dfd.resolve('banana');
 }, 1000);
 return dfd.promise();
}

function asyncThing2() {
  var dfd = $.Deferred();
    setTimeout(function() {
    msg('asyncThing2 seems to be done...');
    dfd.resolve('apple');
  }, 500);
  return dfd.promise();
}

function asyncThing3() {
  var dfd = $.Deferred();
  setTimeout(function() {
    msg('asyncThing3 seems to be done...');
    dfd.resolve('orange');
  }, 1500);
  return dfd.promise();
}

/* do it */
$.when(asyncThing1(), asyncThing2(), asyncThing3()).done(function(res1, res2, res3) {
  msg('all done!');
  msg(res1 + ', ' + res2 + ', ' + res3);
});

Live Demo @ JSFiddle

任意延期电话Original SO Post

//Push all arbitrary ajax calls to deferred array
var deferreds = [];
function getSomeDeferredStuff() {
   var i = 1;
   for (i = 1; i <= 10; i++) {
      var count = i;
      deferreds.push(
        $.post('/echo/html/', {
          html: "<p>Task #" + count + " complete.",
          delay: count
        }).success(function(data) {
           $("div").append(data);
      }));
   }
}


// define a extension method for $.when for creating/managing deferred
// objects for every ajax call
if (jQuery.when.all===undefined) {
   jQuery.when.all = function(deferreds) {
      var deferred = new jQuery.Deferred();
      $.when.apply(jQuery, deferreds).then(
          function() {
             var deferredObjs= function (arguments) { return deferreds.length > 1 ? $.makeArray(arguments) : [arguments]; }
             deferred.resolve(deferredObjs);
          },
          function() {
             deferred.fail(deferredObjs);
          });

      return deferred;
   }
}

//passing the deferred calls array to $.when
$.when.all(deferreds).then(function(objects) {
    //process when all deferred objects compelted
    console.log("Resolved/rejected objects:", objects);
});

Working example for arbitrary ajax calls @JSFiddle