关于jquery的Deferred的使用

发布于 2021-11-25 12:04:00 字数 1700 浏览 849 评论 5

实在是抓狂了,主要问题是ajax执行后的延迟上

一般来说ajax执行后用success或者fail就可以了,直接跟在ajax后执行完了了事,但是我现在这个情况是需要三重延迟的

saveData()//这个是保存数据的函数

endEditing()//这个是判断能否结束的函数

clickCell()//这个是触发判断

伪代码及主要如下:

clickCell(){
    $('#debug').append('<br/>');
    $('#debug').append('进入单元格');
    if(endEditing()){
        //开始编辑
        editIndex=getindex();//获取当前编辑的序号
    }
}

endEnding(){
    debug('进入endeding');
    if(editIndex==undefined){return true;}//当前没有编辑
    //当前处于编辑状态
    endedit;//结束编辑
    getchange;//获取改变的数据
    $.when(saveData())   //保存数据
    .done(function()(
        debug('endding done');
        editIndex=undefined;//清空编辑状态
        return true;
    )).fail(function(){
        return false;
    });
    debug('endding debug');
}

saveData(){
    $('#debug').append('<br/>');
    $('#debug').append('进入savedata');
    var dtd = $.Deferred();
    cData=getChange();//获取当前改变的数据
    createData;//和原始数据比较并生成ajax字符串
    if(changed){
        $.ajax({
            datatype:'json'....
        }).done(function(data){
            $('#debug').append('<br/>');
            $('#debug').append('ajax done');
            if(data.success){
                ...
                return dtd.resolve();
            else{
                return dtd.reject();
            }
        });
    }else{
        return dtd.reject();
    }
}



出来后的debug是:

点击单元格index=1
进入endediting
进入savedata
endediting done
endediting debug
ajax done

这里明显不对啊,ajaxdone应该在savedata之后马上执行,然后才是endediting的debug啊!


一直调试不成功,求指点下啊。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

归途 2021-11-28 07:40:21

等你爱我 2021-11-28 06:15:04

没错,按照以上的理解,我原来的代码存在的问题在于:saveData没有返回dtd对象,

这里dtd.resolve和reject只是改变dtd的状态,而dtd的状态则是由when来判断的,因此when调用的时候一定要获得一个dtd(promise)对象

而when是单行语句,一行执行后下一行语句会紧接着执行,需要延迟的代码必须放置在done或者fail里面

而我之前saveData没有返回dtd对象(是在ajax的回调中返回的,而且返回的还是错的),现在在saveData的每个分支出口都返回dtd.promise,然后在每个分支代码的结尾都增加dtd的resolve和reject,然后endEditing也如法炮制,就好了

现在的deubg结果如下:

进入endediting
进入savedata
endediting debug
ajax done
endediting done

整个人都舒畅起来了~

像你 2021-11-28 06:00:38

http://jsfiddle.net/q9TvT/重新进行了测试

代码如下:

function wait(){

   var dtd = $.Deferred(); //在函数内部,新建一个Deferred对象
      $.ajax("/echo/json/")
      .done(function(){
          alert(2);
          dtd.reject();
      });
   return dtd.promise(); // 返回promise对象

  };

function edit(){
    var dtd=$.Deferred();

  $.when(wait())

  .done(function(){ 
      alert("哈哈,成功了!"); 
      dtd.resolve();
  })

  .fail(function(){ 
      alert("出错啦!"); 
      dtd.reject();
  });
    return dtd.promise();
    
}
$.when(edit())
.done(function(){
    alert('edit done');
})
.fail(function(){
    alert('edit fail');
})

换个说法,将其理解为多线程等待及数据交换的话应该好理解一些。

深巷少女 2021-11-27 19:46:07

引用来自“con”的评论

用法上有俩地方:

1、$.when()方法传入的参数应该是一个Deferred对象,这样才能在Deferred对象resolve后执行done函数,dtd.resolve()的返回值我没有测试,应该不会返回dtd本身,猜是undefined

2、$.ajax本身是一个Deferred对象,saveData()里面若直接返回$.ajax,是可以等待ajax请求完之后触发$.when().done()的,但是例子中有分支是不需要执行ajax的,所以使用这个方式不行

====================================

下面是重点,关于例子的写法

1、endEditing函数中,不使用$.when,使用var dfd = $.Deferred();

把$.when的done写到dfd的done中,dfd.done(function(){...})

2、savaData函数接收一个参数dfd(Deferred对象),成功时执行dfd.resolve(),失败时执行dfd.reject(),函数中不再创建Deferred对象,使用传入的参数

3、endEditing函数中调用saveData时,把dfd传入saveData

秋意浓 2021-11-26 19:06:57

用法上有俩地方:

1、$.when()方法传入的参数应该是一个Deferred对象,这样才能在Deferred对象resolve后执行done函数,dtd.resolve()的返回值我没有测试,应该不会返回dtd本身,猜是undefined

2、$.ajax本身是一个Deferred对象,saveData()里面若直接返回$.ajax,是可以等待ajax请求完之后触发$.when().done()的,但是例子中有分支是不需要执行ajax的,所以使用这个方式不行

====================================

下面是重点,关于例子的写法

1、endEditing函数中,不使用$.when,使用var dfd = $.Deferred();

把$.when的done写到dfd的done中,dfd.done(function(){...})

2、savaData函数接收一个参数dfd(Deferred对象),成功时执行dfd.resolve(),失败时执行dfd.reject(),函数中不再创建Deferred对象,使用传入的参数

3、endEditing函数中调用saveData时,把dfd传入saveData

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文