关于jquery的Deferred的使用
实在是抓狂了,主要问题是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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
没错,按照以上的理解,我原来的代码存在的问题在于: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
整个人都舒畅起来了~
在http://jsfiddle.net/q9TvT/重新进行了测试
代码如下:
换个说法,将其理解为多线程等待及数据交换的话应该好理解一些。
引用来自“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
用法上有俩地方:
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