[译文]jQuery的Deferred

?? jQuery的$.Deferred()命令是该函数库中近来最强大的命令。它并非是一个新观念,但对于数以千计的前端开发人员来说是极有价值的。从核心来看,Deferred非常的简单,但却是一个很强大的异步管理的工具。众所周知开发前端时,经常需要进行异步的处理。

?? 我们把焦点放在Deferred以及jQuery在这方面所提供的API。下面有许多丰富的范例。读完后,你将会了解到什么是Deferred以及何时使用它。

了解核心概念

?? Deferred本质上就是一个Proxy对象,它可以套用到任何异步处理: Ajax请求,动画,或是Web Worker。使用者行为在设计上可以采用延迟处理;在页面上的表单,Deferred允许你可以指定当发生错误或顺利完成时要进行怎样的处理。jQuery允许你注册链函数,该函数会在Deferred判定成功时,或是发生错误,或是告知正处于某种状态时被调用。

?? 你可能已经使用过Deferred。jQuery的Ajax方法回传的对象已经实做了Deferred界面。这个对象会解析Ajax请求是成功或是失败。

有一个很重要你必须要知道的东西

?? Deferred抽象来看是让开发人员避开异步处理。Deferred可以无限延展,而链函数可以持续的在Deferred对象生命周期中添加。这种手法的关键在于Deferred的链函数会在Deferred解析完状态之后立刻被调用。你不需要去担心异步的计算单元(例:Ajax请求)是否已完成。系结到Deferred的链函数会在Deferred在当下或待会解析出执行状态后被执行。

使用jQuery的Deferred

解析和拒绝

?? Deferred的核心方法就是你需要去处理Deferred对象的解析或拒绝。你可以使用$.Deferred()方法创建一个新的Deferred对象。该对象的done()方法会在Deferred被解析被执行,而fail()方法则是在Deferred对象被拒绝时执行。实际上,解析或拒绝一个Deferred对象将以借由resolve()和reject()来达成。本质上,jQuery的ajax()方法会在请求成功时调用resolve()方法,而会在请求是错误(例: Http状态为404)时调用reject()方法。

?? 要记得,若你挂载done或fail处理到deferred对象上,且该对象已经解析过了,该函数会立马被执行。

通知Deferreds: notify()和progress()

?? jQuery 1.7亦添加了Progress的概念到Deferred中,这个Progress是针对拒绝和解析用的。progress()允许你挂载Deferred调用notify()方法时的链函数。这让Deferred得以响应"解析状态的目前进度"。Deferred描述一个长时间资源叫用时,就可以在progress()函数上注册一个链函数,并且该函数可以周期性的更新进度列,举例来说,Deferred对象会在载入/载入完成后解析这些状态时被通知目前进度。

回传promis()

?? 在许多案例中,假若你正回传一个Deferred,但你并不想要让这个对象被解析或拒绝-你想要自主控制。在这个情况下,你可以回传promise对象。在jQuery的术语中,promise是一种只读型的Deferred对象。promise允许你挂载链函数并且询问Deferred的状态,但你无法要它改变它自己的状态(例: 解析/拒绝)。jQuery的ajax()方法回传的是promise,因为它自己内部有处理Ajax请求的判定是正确或错误。

借由when()同步所有异步事件

?? $.when()允许一或多个Deferred并且产生一个新的Deferred对象, 该对象只有在所有Deferred对象都解析后才会解析。这可以让你去组合多个异步事件成为一个。

?? 思考下面的范例:

????? 我们的UI请求数据来自于两个独立的Ajax请求,并且它需要这两个请求都取得数据后才能绘出画面。

?? 没有when(),我会将焦点放在巢状式链函数来确保两个请求已经完成。代价为何?我们需要在两个不同的地方指定错误处理流程。


var name = $.post(‘/echo/json/‘, {json:JSON.stringify({‘name‘: "Matt Baker"})});
var lastUpdate = $.post(‘/echo/json/‘, {json:JSON.stringify({‘lastUpdate‘:"Hello World"})});
name.done(function(nameData) {
   var name = nameData.name;
   lastUpdate.done(function(lastUpdateData) {
      var lastUpdate = lastUpdateData.lastUpdate;
      $("#render-me").html(name + " ‘s last update was: " + lastUpdate);
   }).fail(function() {
      $("#error").html("an error occured").show();
   }).fail(function() {
       $("#error").html("an error occured").show();
   });
});

?? 我们可以使用$.when()来组合两个Ajax请求所回传的Deferred成为一个Deferred对象。该对象只会在两个Ajax请求都完成时才会被解析。我们可以注册一个链函数用来处理UI元素在成功时的呈现。附带一题,我们仅需指定一次错误处理在一个地方。


var name = $.post(‘/echo/json/‘, {json:JSON.stringify({‘name‘:"Matt Baker"}) });
var lastUpdate = $.post(‘/echo/json‘, {json:JSON.stringify({‘lastUpdate‘:"Hello World"})});

$.when(name, lastUpdate)
  .done(function(nameResponse, lastUpdateResponse) {
      var name = nameResponse[0].name;
      var lastUpdate = lastUpdateResponse[0].lastUpdate;
          $("#render-me").html(name+"‘s last update was: "+lastUpdate);
  }).fail(function() {
       $("#error").html("an error occured").show();
});

//为什么数组会出现在done函数中?

//新的done链函数接收所有来自每一个在$.when()中的Deferred对象的done链函数所接收到的数据。

//在本例中,我们取得两个数组,一个是来自传送到done方法链函数的name请求,另一个是传送到done方法链函数的lastUpdate请求。

转换型式成pipe()

?? jQuery中有一个令人感兴趣的Deferred对象的API: pipe()。pipe()允许你将Deferred的结果转型(jQuery称其为过滤器)。你可以提供一个函数用来修改reject()或resolove()传入你链函数的值,或是该函数可以修改Deferred对象的状态。

?? 让我们来看一个范例。考虑以下情境。

????? 你的JSON API是借由JSON响应的某个旗标来描述错误(例: {error:true})而不是借由传送Http状态码来标示错误。你的JSON API总是回传Http状态码200。

?? 在此状况下,假入在Http状态为200下的错误发生了。由于promise只有在Http请求失败时才会是拒绝。这样一来你就必须要自行处理你的错误处理流程于success的链函数中,而不是fail的链函数中。


$.post(‘/echo/json/‘,{json: JSON.stringify({‘error‘:true}) })
   .done(function(response) {
      if(response.error) {
          $("#status").html("An error occurred");
      }else {
         $("#status").html("Success!");
      }
}).fail(function(response) {
    $("#status").html("A server error occured(failing http status code)");
});

?? 很明显地,这不是一个理想的解决方案。借由强大的pipe(),我们就可以创建一个新的Deferred对象,它可以栏截Ajax请求的解析。我们会检查JSON响应中的error旗标。假若为true,则pipe将回传一个已拒绝的Deferred对象,它会令fail的链函数被执行。


var myXhrDeferred =
   $.post(‘/echo/json‘, {json:JSON.stringify({‘error‘:true})})
      .pipe(function(response) {
         if(response.error){
            return $.Deferred().reject(response);
         }
         return response;
      },
      function() {
         return $.Deferred().reject({error:true});
      }
   );

myXhrDeferred .done(function(response) {
   $("#status").html("Success!");
}).fail(function(response) {
   $("#status").html("An error occurred");
});

全民异步

?? 实际上,在你的网站或是应用程序上有着许多的异步。考虑如下情境:

????? 你的网站要求使用者创建一个会员数据。为了要鼓励他们把数据填完,你会显示一个数据完整度进度表。当它们填完后你会想要显示一个"感谢"的消息。

?? 在此案例中,Deferred描述的是会员数据的延迟程度。本质上是在创建或计算填写数据实际上却是计算人类的行为。在这个状况下你可能不会去考虑到异步,但可以借由Deferred来进行验证。我们可以使用notify()来通知使用者行为的Deferred对象(也因此Deferred成了Proxy),并且resolve()可以通知已完成。我们可以在progress()上注册链函数来更新进度表,并且使用done()来显示"感谢"消息。


var userProgress = $.Deferred();
var $profileFileds = $("input");
var totalFields = $profileFields.length;
userProgress.progress(function(filledFields) {
var pctComplete = (filledFields/totalFields)*100;
     $("#progress").html(pctComplete.toFixed(0));
});

userProgress.done(function() {
     $("#thanks").html("Thanks for completing your profile!").show();
});

$("input").on("change", function() {
   var filledFields = $profileFields.filter("[value!=‘‘]").length;
   userProgress.notify(filledFields);
   if(filledFields == totalFields) {
      userProgress.resolve();
   }
});

Deferred无所不在

?? 为了处理每个开发人员都得面对的异步处理,Deferred模式是简单,强大,并且广泛应用的:

?? 1. 在缓存中使用Deferred

?? 2. 更有描述力的setTimeout()

?? 3. jQuery Deferred API的外加范例

?? 4. jQuery Deferred对象API参考

原文链接:http://eng.wealthfront.com/2012/12/jquerydeferred-is-most-important-client.html

原文:大专栏  [译文]jQuery的Deferred

原文地址:https://www.cnblogs.com/chinatrump/p/11496661.html

时间: 2024-10-30 05:04:01

[译文]jQuery的Deferred的相关文章

jquery的Deferred 对象初体验

之前阅读了阮一峰老师的jQuery的deferred对象详解一文,结合jquery手册,算是对Deferred对象有了初步的认知.今天便来分享一下我自己的一些体会. 一.deferred可以方便的添加回调 先来看下面的例子 1 var test = function(callback) { 2 setTimeout(function() { 3 console.log('我完成了'); 4 callback('我是回调') 5 }, 1000) 6 }; 7 test(function(text

jQuery的deferred对象

今天学习jQuery API的时候看到deferred部分,以前也没有接触使用过,看的毫无头绪,于是找资料学习了一番. deferred对象代表了将要完成的某种操作,并提供了一些方法,帮助用户使用.它是jQuery对Promises接口的实现.由于JavaScript单线程的特点,如果某个操作耗时很长,其他操作就必需排队等待.为了避免整个程序失去响应,通常的解决方法是将那些排在后面的操作,写成“回调函数”(callback)的形式.这样做虽然可以解决问题,但是有一些显著缺点: 回调函数往往写成函

jQuery之Deferred对象

Deferred对象是由$.Deferred构造的,$.Deferred被实现为简单工厂模式. 它用来解决JS中的异步编程,它遵循 Common Promise/A 规范.实现此规范的还有 when.js 和 dojo. $.Deferred作为新特性首次出现在版本1.5中,这个版本利用Deferred又完全重写了Ajax模块. $.Deferred在jQuery代码自身四处被使用,分别是promise方法.DOM ready.Ajax模块.动画模块. 这里以版本1.8.3分析,由于1.7后$.

jQuery的deferred对象详解(转)

jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. 这个功能很重要,未来将成为jQuery的核心方法,它彻底改变了如何在jQuery中使用ajax.为了实现它,jQuery的全部ajax代码都被改写了.但是,它比较抽象,初学者很难掌握,网上的教程也不多.所以,我把自己的学习笔记整理出来了,希望对大家有用. 本文不是初级教程,针对的读者是那些已经具备

jQuery之Deferred源码剖析

一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样,通过链式调用,避免层层嵌套,如下: //jquery版本大于1.8 function runAsync(){ var def = $.Deferred(); setTimeout(function(){ console.log('I am done'); def.resolve('whatever'

jquery 之 Deferred 使用与实现

观察者模式是开发中经常使用的模式,这个模式由两个主要部分组成:主题和观察者.通过观察者模式,实现主题和观察者的解耦. 主题负责发布内容,而观察者则接收主题发布的内容.通常情况下,观察者都是多个,所以,我们需要一个集合来保存所有的观察者,在主题发布内容之后,依次将主题发布的内容提供给观察者,从程序的角度来说,观察者就是一堆的方法,我们将内容作为参数依次调用这些方法. 如果你已经看过上一篇 jQuery 之 Callbacks, 那么,你会发现,通过 Callbacks 来管理观察者的列表是很方便的

jQuery的deferred对象详解(转)

jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. 这个功能很重要,未来将成为jQuery的核心方法,它彻底改变了如何在jQuery中使用ajax.为了实现它,jQuery的全部ajax代码都被改写了.但是,它比较抽象,初学者很难掌握,网上的教程也不多.所以,我把自己的学习笔记整理出来了,希望对大家有用. 本文不是初级教程,针对的读者是那些已经具备

jQuery的deferred对象详解(二)

Deferred对象是由$.Deferred构造的,$.Deferred被实现为简单的工厂模式. $.Deferred的实现 创建三个$.Callbacks对象,分别表示成功done,失败fail,处理中process三种状态 对应了三种处理结果,resolve.reject.notify 创建了一个promise对象,具有state.always.then.primise方法 通过扩展primise对象生成最终的Deferred对象,是阻止其他代码来改变这个deferred对象的状态,defe

jQuery的deferred对象详解(一)

最近一段时间,都在研究jquery里面的$.Deffered对象,几天都搞不明白,其中源码的运行机制,网上查找了相关的资料,<jQuery的deferred对象详解>阮一峰老师的文章,里面阐述deferred讲的非常清楚,也让我大彻大悟,为了以后能很好的查阅,现将阮老师的文字转载过来. 一.什么是deferred对象? 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作.其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即