源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

在jQuery 1.5中使用deferred对象的代码(翻译)

  • 时间:2020-04-10 09:05 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:在jQuery 1.5中使用deferred对象的代码(翻译)
译者注: 1. Deferred是jQuery1.5新增的一个特性,很多人把它翻译成 “异步队列”,我觉得比较靠谱,毕竟和“延迟”没啥关系,不过这篇文章中我还采用deferred这个单词。 2. 这篇文章在jQuery1.5发布博客中提到,也是目前介绍deferred比较经典和深入的文章。鉴于目前中文资料比较少,特别翻译出来供大家学习参考。 3. 通篇采用意译的方式,如有不当还请大家提出。 jQuery1.5中新增的Deferreds对象,可以将任务完成的处理方式与任务本身解耦合。这在JavaScript社区没什么新意,因为Mochikit和Dojo两个JS框架已经实现了这个特性很长一段时间了。但是随着[url=http://jaubourg.net/]Julian Aubourg[/url]对jQuery1.5中AJAX模块的重写,deferreds理所当然成为了内部的实现逻辑。使用deferreds对象,多个回调函数可以被绑定在任务完成时执行,甚至可以在任务完成后绑定这些回调函数。这些任务可以是异步的,也可以是同步的。 更重要的是,deferreds已经作为$.ajax()的内部实现,所以你可以在调用AJAX时自动获取deferreds带来的遍历。比如我们可以这样绑定回调函数:
[url=http://jsfiddle.net/ehynds/Mrqf8/]在jsFiddle中打开示例[/url] 上面的示例能够正常运行,这要归功于每个jQuery的AJAX方法返回值都包含一个promise函数,用来跟踪异步请求。[b]Promise函数的返回值是deferred对象的一个只读视图。(The promise is a read-only view into the result of the task.)[/b]Deferreds通过检测对象中是否存在promise()函数来判断当前对象是否可观察。$.when()会等待所有的AJAX请求结束,然后调用通过 .then(), .fail()注册的回调函数(具体调用哪些回调函数取决于任务的结束状态)。这些回调函数会按照他们的注册顺序执行。 更好的是,$.when()接受函数或者函数的数组为参数(译者注:这点不大对,$.when接受一个或多个deferred对象,或者原生的JS对象。注意不能以函数数组为参数),这样你就可以随意组合这些异步任务。 $.ajax()返回一个对象,这个对象关联一些deferred函数,比如promise(), then(), success(), error()。然而你不能操作原始的deferred对象,只有promise()函数(译者注:还记得刚才提到的promise是只读视图),以及可以检测deferred状态的isRejected() 以及isResolved()函数。 但是为什么不返回deferred对象呢?如果返回了完整的deferred对象,那么我们就拥有更多的控制,或许可以随意的触发(译者注:我把resolve翻译成触发,就是触发所有注册到deferred对象上的回调函数)deferred对象,从而导致所有回调函数在AJAX请求结束之前执行。[b]因此,为了避免不期望的触发deferred的风险,我们应该只返回dfd.promise()[/b].([b]Therefore, to avoid potentially breaking the whole paradigm, only return the dfd.promise()[/b].)(译者注:如果你很迷惑上面几段话的确切意思,没关系,我随后会写一篇文章深层次分析其中原因 注册回调函数(Registering Callbacks) 上面的例子中,我们使用then(), success(), fail()方法来注册回调函数,其实还有更多的方法可以使用,特别在处理AJAX请求时。具体使用哪种方式取决于你对结果状态的关注。 所有deferred对象都有的函数 (AJAX, $.when 或者手工创建的deferred对象):
[url=http://jsfiddle.net/ehynds/JSw5y/]在jsFiddle中打开示例[/url] 在showDiv()中,我们创建了一个deferred对象,执行了一段动画,然后返回promise。这个deferred对象会在fadeIn()结束后被触发(resolved)。在这个promise返回和deferred对象(注意:这里的deferred指的是$.when创建的对象,而非showDiv()返回的对象)触发的中间,一个then()回调函数会被注册。这个回调函数会在两个异步的任务全部结束后执行。 getData()返回一个对象(译者注:其实是jQuery封装的XMLHttpRequest对象)拥有promise方法,这就允许$.when()监视本次AJAX请求的结束。The manually steps we took to return a promise in showDiv() is handled for us internally by $.ajax() and $.when(). 1/15/2011: Julian在评论中指出,上面的语法可以被简化为$.Deferred(fn).promise()。因此下面的两端代码是等价的:
[url=http://jsfiddle.net/ehynds/W3cQc/]在jsFiddle中打开示例[/url] 链式代码(Chaining Hotness) Deferred的回调函数可以链式调用,只要函数返回的是deferred对象(译者注:dfd.promise()返回的是只读的deferred对象)。这是一个实际的代码 (via @ajpiano!)
[u]复制代码[/u] 代码如下:
function saveContact(row) { var form = $.tmpl(templates["contact-form"]), valid = true, messages = [], dfd = $.Deferred(); /* * 这里方式客户端验证代码 */ if (!valid) { dfd.resolve({ success: false, errors: messages }); } else { form.ajaxSubmit({ dataType: "json", success: dfd.resolve, error: dfd.reject }); } return dfd.promise(); }; saveContact(row).then(function (response) { if (response.success) { // 客户端验证通过,并且保存数据成功 } else { // 客户端验证失败 // 输出错误信息 } }).fail(function (err) { // AJAX请求失败 });
saveContact()函数首先验证表单数据的有效性,然后把有效性状态保存在变量valid中。如果验证失败,直接deferred会被触发(把一个包含success状态码和错误信息的JS对象作为参数传递给回调函数)。如果验证通过,则向服务器提交数据,在AJAX成功完成后触发deferred对象。fail()会处理404, 500等可以阻止AJAX请求成功完成的HTTP状态码。 不可观察的任务(Non-observable Tasks) Deferreds对于解耦任务与任务处理函数时非常有用,而不管是异步任务或者同步任务。一个任务可能会返回promise,但也可以返回字符串,对象或者其他类型。 在这个例子中,当“Lanch Application”链接被首次点击时,一个AJAX请求会发送到服务器并返回当前时间戳。然后这个时间戳会被保存到这个链接的data缓存中。当这个链接再次被点击时,只是简单的从缓存中取出这个时间戳返回,而不会发出AJAX请求。
[u]复制代码[/u] 代码如下:
function startTask(element) { var timestamp = $.data(element, 'timestamp'); if (timestamp) { return timestamp; } else { return $.get('/start-task/').success(function (timestamp) { $.data(element, 'timestamp', timestamp); }); } } $('#launchApplication').bind('click', function (event) { event.preventDefault(); $.when(startTask(this)).done(function (timestamp) { $('#status').html('<p>You first started this task on: ' + timestamp + '</p>'); }); loadApplication(); });
当$.when()发现它的第一个参数没有promise函数(因此不可观察),它就会创建一个新的deferred对象,触发deferred对象,并返回promise只读对象。因此,任意不可观察的任务也能传递到$.when()中。 需要注意的一个问题是,如果一个对象自身拥有promise函数,则这个对象将不能作为deferred对象。jQuery判断一个对象是否deferred,是通过查看它是否有promise函数来决定的,但是jQuery并不会检查这个promise是否真的返回一个可用的对象。因此下面的代码将会出错:
[u]复制代码[/u] 代码如下:
var obj = { promise: function () { // do something } }; $.when(obj).then(fn);
结论(Conclusion) Deferreds提出了一种新的健壮的方式来处理异步任务。和传统的将代码组织到一个回调函数中不同,新的deferred对象允许我们在任何时候(甚至在任务结束后)绑定多个回调函数,而这些回调函数会以先进先出的方式被调用。这篇文章中的信息可能比较难以消化,不过一旦你掌握了deferred对象的使用,你会发现组织异步执行的代码将会非常容易。 本文章由三生石上原创,博客园首发,转载请注明出处
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部