在$ .Deferred.done()中很快调用

时间:2014-08-20 05:40:09

标签: javascript jquery jquery-deferred

这是一个展示我问题的例子。

$.fn.Heartbeat = function(){
  console.log('started');
  $.ajax({
    url:baseurl.php,
    .
    .
    .
    success: function(data){
      //DO SOME STUFF
      console.log('end of success');
    }
} 

$.when($('.mydiv').Heartbeat()).done(function(){console.log('after done');});

此代码输出:

started

after done

end of success

虽然我想:

started

end of success

after done

我的意思是,DONE中的函数必须在Heartbeat完成后执行,否则它不会完成。

2 个答案:

答案 0 :(得分:2)

这是一种奇怪的方法,但首先你需要将Heartbeat函数添加到jQuery的原型中才能链接它。

其次,你需要将承诺从ajax函数返回到$.when,只有这样才能在promise解析时执行done回调,就像这样

$.fn.Heartbeat = function () {
    console.log('started');
    return $.ajax({
        url: 'baseurl.php',
        success: function (data) {
            //DO SOME STUFF
            console.log('end of success');
        }
    });
}

$.when($('.mydiv').Heartbeat()).done(function () {
    console.log('after done');
});

FIDDLE


要为每个元素发送ajax请求,并在所有请求成功完成后解析promise,您可以

$.fn.Heartbeat = function () {
    console.log('started');

    var def = new Deferred();

    $.when.apply(undefined, 
        $.map(this, function() {
            return $.ajax({
                url: '/echo/html/',
                success: function (data) {
                    //DO SOME STUFF
                    console.log('end of success');
                }
            });
        })
    ).then(def.resolve);

    return def.promise();
}

$('.mydiv').Heartbeat().done(function () {
    console.log('after done');
});

答案 1 :(得分:0)

$.when()不是魔法。它不知道何时传递给它的某个函数。相反,你必须传递一个承诺,然后它将知道该承诺何时完成。因为您没有从Hearbeat()函数返回承诺,$.when()不知道该ajax调用何时实际完成,因此它将其视为同步事件。

这是一种更简单的方法:

var Heartbeat = function(){
  console.log('started');
  return $.ajax({
    url:baseurl.php,
    // other args
  }).then(function(data) {
        //DO SOME STUFF
        console.log('end of success');
  });
} 

Heartbeat().done(function(){
   console.log('after done');
});

的变化:

  1. 您必须从Heartbeat返回承诺,以便.done()可以等待它
  2. 无需使用$.when()作为单一承诺 - 只需对该承诺使用.then()
  3. Heartbeat是常规函数(不是jQuery方法),因此您将其称为常规函数。由于该函数不以任何方式使用jQuery对象,我认为没有任何理由将其作为jQuery方法。
  4. 切换成功处理程序以使用.then(),因为您正在使用promises
  5. 修复parens和支撑是合法的JS