代码之家  ›  专栏  ›  技术社区  ›  Ferex

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

  •  1
  • Ferex  · 技术社区  · 11 年前

    这是一个例子来说明我的问题。

    $.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

    当我想要:

    起动

    成功的终点

    完成后

    我的意思是,DONE内的函数必须在心跳完成后执行,否则就不能执行。

    2 回复  |  直到 11 年前
        1
  •  2
  •   adeneo    11 年前

    这是一种奇怪的方法,但首先需要添加 Heartbeat 函数到jQuery的原型,以便能够将其链接起来。

    其次,需要将ajax函数的promise返回到 $.when ,只有这样 done 当promise解析时执行回调,如下所示

    $.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请求,并在所有请求成功完成后解决承诺,可以执行以下操作

    $.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');
    });
    
        2
  •  0
  •   jfriend00    11 年前

    $.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() 因为你在用承诺
    5. 将括号和支撑固定为合法JS