>

jQuery的Deferred对象概述,jQuery之Deferred对象详解

- 编辑:至尊游戏网站 -

jQuery的Deferred对象概述,jQuery之Deferred对象详解

jQuery的Deferred对象概述

2017/03/02 · CSS

本文由 伯乐在线 - HansDo 翻译,叙帝利 校稿。未经许可,制止转发!
俄语出处:Aurelio De Rosa。招待参与翻译组。

比较久以来,JavaScript 开辟者们习贯用回调函数的办法来施行一些职务。最分布的例证便是运用 addEventListener()函数来加多二个回调函数, 用来在钦定的事件(如 clickkeypress)被触发时,实行生龙活虎层层的操作。回调函数轻便实用——在逻辑并不复杂的时候。缺憾的是,意气风发旦页面包车型客车复杂度扩展,而你由此须求进行非常多相互或串行的异步操作时,那个回调函数会让你的代码难以保证。

ECMAScript 二〇一六(又名 ECMAScript 6) 引进了一个原生的法子来消除那类难点:promises。若是你还不亮堂 promise 是什么,能够翻阅那篇文章《Javascript Promise概述》。jQuery 则提供了独具匠心的另风度翩翩种 promises,叫做 Deferred 对象。何况 Deferred 对象的引进时间要比 ECMAScript 引进 promise 早了一些年。在这里篇随笔里,笔者会介绍 Deferred 对象和它试图缓慢解决的难点是怎么着。

deferred对象是jQuery对Promises接口的落到实处。它是非同步操作的通用接口,能够被看作是一个守候实现的天职,开拓者通过一些经过的接口对其开展安装。事实上,它扮演代理人(proxy)的角色,将那么些非同步操作包装成富有有个别统后生可畏个性的目的,规范例子正是Ajax操作、网页动画、web worker等等。

Deferred对象简史

Deferred对象是在 jQuery 1.5中引进的,该目的提供了风流倜傥种类的主意,能够将三个回调函数注册进叁个回调队列里、调用回调队列,以至将同步或异步函数实施结果的名利双收恐怕诉讼失败传递给相应的管理函数。从这未来,Deferred 对象就成了商讨的话题, 此中不乏批评意见,这一个观点也一直在扭转。一些优秀的争辩的见识如《你并未知晓 Promise 》和《论 Javascript 中的 Promise 以至 jQuery 是怎么样把它搞砸的》。

Promise 对象 是和 Deferred 对象一齐作为 jQuery 对 Promise 的意气风发种实现。在 jQuery1.x 和 2.x 版本中, Deferred 对象信守的是《CommonJS Promises 提案》中的约定,而 ECMAScript 原生 promises 方法的确立基础《Promises/A+ 提案》也是以这意气风发议事原案书为底蕴衍生而来。所以就如大家一齐首波及的,之所以 Deferred 对象未有依照《Promises/A+ 议事原案》,是因为那时候后面一个根本尚未被构想出来。

由于 jQuery 扮演的先行者的剧中人物以致后向包容性难题,jQuery1.x 和 2.x 里 promises 的应用格局和原生 Javascript 的用法并不雷同。其余,由于 jQuery 本身在 promises 方面依据了其它朝气蓬勃套议事原案,那变成它不可能协作其余完毕promises 的库,比如 Q library。

唯独就要到来的 jQuery 3 改进了 同原生 promises(在 ECMAScript二零一六中贯彻)的互操作性。即使为了向后非凡,Deferred 对象的显要方法之生龙活虎(then())的办法签名仍旧会微微差异,但行为方面它早已同 ECMAScript 2014 标准更是风度翩翩致。

jQuery的具备Ajax操作函数,暗中认可重临的便是一个deferred对象。

jQuery中的回调函数

举一个例证来通晓为何大家须求用到 Deferred指标。使用 jQuery 时,平常会用到它的 ajax 方法实施异步的多寡须求操作。大家无妨假若你在开拓三个页面,它能够发送 ajax 恳求给 GitHub API,指标是读取贰个客户的 Repository 列表、定位到近些日子翻新贰个Repository,然后找到第三个名叫“README.md”的文书并赢得该公文的内容。所以基于以上描述,每贰个号令独有在前一步成功后本事发轫。换言之,那个伏乞必得各样实施

上面包车型地铁呈报能够调换来伪代码如下(注意本人用的而不是确实的 Github API):

JavaScript

var username = 'testuser'; var fileToSearch = 'README.md'; $.getJSON('' + username + '/repositories', function(repositories) { var lastUpdatedRepository = repositories[0].name; $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/files', function(files) { var README = null; for (var i = 0; i < files.length; i++) { if (files[i].name.indexOf(fileToSearch) >= 0) { README = files[i].path; break; } } $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content', function(content) { console.log('The content of the file is: ' + content); }); }); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var username = 'testuser';
var fileToSearch = 'README.md';
 
$.getJSON('https://api.github.com/user/' + username + '/repositories', function(repositories) {
  var lastUpdatedRepository = repositories[0].name;
 
$.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/files', function(files) {
    var README = null;
 
for (var i = 0; i < files.length; i++) {
      if (files[i].name.indexOf(fileToSearch) >= 0) {
        README = files[i].path;
 
break;
      }
    }
 
$.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content', function(content) {
      console.log('The content of the file is: ' + content);
    });
  });
});

如你所见,使用回调函数的话,我们需求每每嵌套来让 ajax 诉求根据大家期待的相继实行。今世码里现身多数嵌套的回调函数,只怕有成都百货上千相互独立但要求将它们一同的回调时,大家往往把这种气象称作“回调鬼世界( callback hell )“。

为了多少修正一下,你能够从本人成立的无名氏函数中提抽取命名函数。但那支援并十分的小,因为大家依然在回调的苦海中,照旧面临着回调嵌套和协助举行的难点。那时是 DeferredPromise指标登场的时候了。

Promises是什么

Deferred和Promise对象

Deferred 对象可以被用来举办异步操作,比方 Ajax 央浼和卡通片的落到实处。在 jQuery 中,Promise指标是只可以由Deferred对象或 jQuery 对象创立。它装有 Deferred 对象的风华正茂部分方法:always(),done(), fail(), state()then()。大家在下豆蔻梢头节会讲到这一个办法和任何细节。

大器晚成旦你来自于原生 Javascript 的社会风气,你大概会对那多个指标的留存认为吸引:为啥 jQuery 有八个对象(DeferredPromise)而原生JS 独有一个(Promise)? 在自家撰文的书《jQuery 实践(第三版)》里有二个类比,能够用来评释这一个难题。

Deferred对象日常用在从异步操作重临结果的函数里(重返结果大概是 error,也或许为空)——即结果的生产者函数里。而回到结果后,你不想让读取结果的函数改变Deferred 对象的状态(译者注:包蕴 Resolved 分析态,Rejected 回绝态),那时就能够用到 promise 对象——即 Promise 对象总在异步操作结果的消费者函数里被选用。

为了理清那个定义,大家若是你必要实现叁个基于 promise 的timeout()函数(在本文稍后交易会示这几个事例的代码)。你的函数会等待钦点的大器晚成段时间后回来(这里未有再次来到值),即多少个生产者函数而以此函数的呼应消费者们并不在乎操作的结果是水到渠成(深入分析态 resolved)依然战败(拒绝态 rejected),而只关切他们需求在 Deferred 对象的操作成功、战败,也许摄取进展通告后继之实践一些别样函数。别的,你还期望能保险花费者函数不会活动解析或谢绝Deferred对象。为了完结这一指标,你一定要在劳动者函数timeout()中开创 Deferred 对象,并只回去它的 Promise 对象,并非Deferred对象自己。那样一来,除了timeout()函数之外就从未人能够调用到resolve()reject()进而修改Deferred 对象的情景了。

在这个 StackOverflow 问题 里你能够通晓到越多关于 jQuery 中 Deferred 和 Promise 对象的不如。

既是您曾经通晓里那多个对象,让大家来看一下它们都含有哪些措施。

由于JavaScript单线程的特点,假使有些操作耗时不长,其余操作就必得排队等候。为了幸免全数程序失去响应,日常的缓和方式是将那么些排在后边的操作,写成“回调函数”(callback)的情势。那样做固然能够解决难点,不过有意气风发对大名鼎鼎劣点:

Deferred对象的办法

Deferred对象格外灵活并提供了您只怕必要的有着办法,你能够透过调用 jQuery.Deferred() 像上边同样创造它:

JavaScript

var deferred = jQuery.Deferred();

1
var deferred = jQuery.Deferred();

或者,使用 $作为 jQuery 的简写:

JavaScript

var deferred = $.Deferred();

1
var deferred = $.Deferred();

创建完 Deferred指标后,就能够使用它的一异彩纷呈措施。处了曾经被撇下的 removed 方法外,它们是:

  • always(callbacks[, callbacks, ..., callbacks]): 增加在该 Deferred 对象被深入解析或被反驳回绝时调用的管理函数
  • done(callbacks[, callbacks, ..., callbacks]): 加多在该 Deferred 对象被深入分析时调用的管理函数
  • fail(callbacks[, callbacks, ..., callbacks]): 增多在该 Deferred 对象被反驳回绝时调用的管理函数
  • notify([argument, ..., argument]):调用 Deferred 对象上的 progressCallbacks 管理函数并传递拟定的参数
  • notifyWith(context[, argument, ..., argument]): 在制订的前后文中调用 progressCallbacks 管理函数并传递制定的参数。
  • progress(callbacks[, callbacks, ..., callbacks]): 增添在该 Deferred 对象发生进展通告时被调用的管理函数。
  • promise([target]): 返回 Deferred 对象的 promise 对象。
  • reject([argument, ..., argument]): 拒绝多个 Deferred 对象并以钦命的参数调用全体的failCallbacks管理函数。
  • rejectWith(context[, argument, ..., argument]): 拒却三个 Deferred 对象并在钦点的上下文中以内定参数调用全部的failCallbacks处理函数。
  • resolve([argument, ..., argument]): 分析叁个 Deferred 对象并以钦命的参数调用全数的 doneCallbackswith 管理函数。
  • resolveWith(context[, argument, ..., argument]): 拆解解析贰个 Deferred 对象并在钦定的上下文中以钦命参数调用全体的doneCallbacks处理函数。
  • state(): 重返当前 Deferred 对象的图景。
  • then(resolvedCallback[, rejectedCallback[, progressCallback]]): 增添在该 Deferred 对象被解析、拒绝或收取进展通告时被调用的管理函数

从以上那写方法的描述中,作者想杰出重申一下 jQuery 文书档案和 ECMAScript 标准在术语上的例外。在 ECMAScript 中, 无论三个 promise 被成功 (fulfilled) 依然被推却 (rejected),大家都说它被深入分析 (resolved) 了。然则在 jQuery 的文书档案中,被深入分析这一个词指的是 ECMAScript 规范中的完毕(fulfilled) 状态。

鉴于地方列出的措施太多, 这里无法风姿浪漫生龙活虎详述。可是在下大器晚成节会有多少个展现 DeferredPromise用法的演示。第二个例子中大家会使用Deferred 对象重写“ jQuery 的回调函数”那大器晚成节的代码。第二个例子里作者会证明此前商讨的生产者–消费者其生龙活虎比喻。

1.回调函数往往写成函数参数的款式,导致函数的输入和出口极度混乱,整个程序的可阅读性差;
2.回调函数往往只好内定三个,如若有八个操作,就要求改写回调函数。
3.总体程序的运维流程被打乱,除错和调治将养的难度都对应增加。

使用 Deferred 依次试行 Ajax 请求

那生龙活虎节我会利用Deferred目的和它提供的艺术使“jQuery 的回调函数”那黄金年代节的代码更兼具可读性。但在八只扎进代码早先,让我们先搞明白豆蔻梢头件事:在 Deferred 对象共处的法子中,咱们需求的是哪些。

传闻我们的急需及上文的章程列表,很显著大家既可以够用 done()也能够因而 then()来拍卖操作成功的景色,思考到许多个人早已习感觉常了采纳JS 的原生 Promise指标,这么些示例里本身会用 then()方法来落实。要潜心 then()done()这两个之间的二个根本差别是 then()可以预知把选用到的值通过参数字传送递给后续的 then(),done(),fail()progress()调用。

故而最后我们的代码应该像上边那样:

JavaScript

var username = 'testuser'; var fileToSearch = 'README.md'; $.getJSON('' + username + '/repositories') .then(function(repositories) { return repositories[0].name; }) .then(function(lastUpdatedRepository) { return $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/files'); }) .then(function(files) { var README = null; for (var i = 0; i < files.length; i++) { if (files[i].name.indexOf(fileToSearch) >= 0) { README = files[i].path; break; } } return README; }) .then(function(README) { return $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content'); }) .then(function(content) { console.log(content); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var username = 'testuser';
var fileToSearch = 'README.md';
 
$.getJSON('https://api.github.com/user/' + username + '/repositories')
  .then(function(repositories) {
    return repositories[0].name;
  })
  .then(function(lastUpdatedRepository) {
    return $.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/files');
  })
  .then(function(files) {
    var README = null;
 
for (var i = 0; i < files.length; i++) {
      if (files[i].name.indexOf(fileToSearch) >= 0) {
        README = files[i].path;
 
break;
      }
    }
 
return README;
  })
  .then(function(README) {
    return $.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content');
  })
  .then(function(content) {
    console.log(content);
  });

如你所见,由于我们能够把全部操作拆分成同在一个缩进层级的顺序步骤,这段代码的可读性已经了解增进了。

Promises正是为着清除那么些主题素材而建议的,它的首要性指标就是代表回调函数,成为非同步操作的缓慢解决方案。它的宗旨绪想就是让非同步操作重临三个对象,别的操作都针对这几个目的来成功。比方,假定ajax操作重返多个Promise对象。

创建三个基于 Promise 的 setTimeout 函数

您也许已经领悟 setTimeout() 函数能够在延迟贰个加以的小时后实行某个回调函数,只要您把日子和回调函数作为参数字传送给它。假如你想要在豆蔻梢头分钟后在调控台打字与印刷一条日志消息,你能够用它这样写:

JavaScript

setTimeout( function() { console.log('等待了1秒钟!'); }, 1000 );

1
2
3
4
5
6
setTimeout(
  function() {
    console.log('等待了1秒钟!');
  },
  1000
);

如您所见,setTimeout的率先个参数是要推行的回调函数,第二个参数是以阿秒为单位的等候时间。那么些函数数年以来运转卓绝,但假如今日你供给在 Deferred指标的秘籍链中引进生龙活虎段时间的延时该如何做吧?

上边包车型客车代码展现了哪些用 jQuery 提供的 Promise指标创制贰个依照 promise 的 setTimeout(). 为了达到大家的目标,这里运用了 Deferred对象的 promise()方法。

代码如下:

JavaScript

function timeout(milliseconds) { //创立二个新Deferred var deferred = $.Deferred(); // 在钦命的皮秒数之后深入解析Deferred对象 setTimeout(deferred.resolve, milliseconds); // 重回Deferred对象的Promise对象 return deferred.promise(); } timeout(1000).then(function() { console.log('等待了1分钟!'); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function timeout(milliseconds) {
  //创建一个新Deferred
  var deferred = $.Deferred();
 
// 在指定的毫秒数之后解析Deferred对象
  setTimeout(deferred.resolve, milliseconds);
 
// 返回Deferred对象的Promise对象
  return deferred.promise();
}
 
timeout(1000).then(function() {
  console.log('等待了1秒钟!');
});

这段代码里定义了五个名叫 timeout()的函数,它包裹在 JS 原生的 setTimeout()函数之外。

timeout()里, 成立了贰个 Deferred目的来实现在延迟内定的微秒数之后将 Deferred 对象深入分析(Resolve)的功用。这里 timeout()函数是值的劳动者,因而它担当创设 Deferred对象并赶回 Promise目的。那样一来调用者(花费者)就不可能再随意深入分析或拒却 Deferred 对象。事实上,调用者只可以通过 done()fail()那般的格局来扩大值重回时要实行的函数。

复制代码 代码如下:

jQuery 1.x/2.x同 jQuery3 的区别

在率先个例证里,我们选取 Deferred对象来搜索名字富含“README.md”的文书, 但并从未思索文件找不到的状态。这种气象能够被视作是操作失利,而当操作失利时,大家兴许必要暂停调用链的推行并直接跳到程序结尾。很自然地,为了兑现那些指标,大家应当在找不到文件时抛出叁个极度,并用 fail()函数来捕获它,就像是 Javascriopt 的 catch()的用法同样。

在死守 Promises/A 和 Promises/A+ 的Curry(比如jQuery 3.x),抛出的丰硕会被调换到二个闭门羹操作 (rejection),进而通过 fail()办法加多的停业条件回调函数会被实施,且抛出的不得了会作为参数字传送给那么些函数。

在 jQuery 1.x 和 2.x中, 未有被抓走的十分会半上落下程序的执行。那五个本子允许抛出的不胜向上冒泡,平日最后会达到 window.onerror。而只要未有定义特别的处理程序,格外音讯就可以被出示,同一时间程序也会告意气风发段落运维。

为了更加好的知情那风度翩翩行为上的区分,让我们看一下从笔者书里摘出来的那风流倜傥段代码:

JavaScript

var deferred = $.Deferred(); deferred .then(function() { throw new Error('一条错误新闻'); }) .then( function() { console.log('第二个成功条件函数'); }, function() { console.log('第一个倒闭条件函数'); } ) .then( function() { console.log('第3个成功条件函数'); }, function() { console.log('第一个倒闭条件函数'); } ); deferred.resolve();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var deferred = $.Deferred();
deferred
  .then(function() {
    throw new Error('一条错误信息');
  })
  .then(
    function() {
      console.log('第一个成功条件函数');
    },
    function() {
      console.log('第一个失败条件函数');
    }
  )
  .then(
    function() {
      console.log('第二个成功条件函数');
    },
    function() {
      console.log('第二个失败条件函数');
    }
  );
 
deferred.resolve();

jQuery 3.x 中, 这段代码会在支配台出口“第八个停业条件函数” 和 “第一个成功条件函数”。原因好似自个儿前边提到的,抛出非常后的图景会被调换到拒却操作进而失利条件回调函数一定会被实行。此外,大器晚成旦那多少个被管理(在这里个例子里被曲折条件回调函数字传送给了第4个then()),后边的打响条件函数就能够被试行(这里是第八个 then()里的功成名就条件函数)。

在 jQuery 1.x 和 2.x 中,除了第2个函数(抛出乖谬特其他特别)之外未有此外函数会被施行,所以您只会在调整台里见到“未管理的极度:一条错误音讯。”

您能够到上面四个JSBin链接中查看它们的奉行结果的不等:

  • jQuery 1.x/2.x
  • jQuery 3

为了更加好的修正它同 ECMAScript二〇一四 的宽容性,jQuery3.x 还给 DeferredPromise指标扩张了三个叫做 catch()的新章程。它能够用来定义当 Deferred对象被屏绝或 Promise对象处于谢绝态时的管理函数。它的函数具名如下:

JavaScript

deferred.catch(rejectedCallback)

1
deferred.catch(rejectedCallback)

能够看看,那几个艺术可是是 then(null, rejectedCallback)的三个急迅方式罢了。

var promise = get('');

总结

这篇小说里笔者介绍了 jQuery 达成的 promises。Promises 让我们能够摆脱那多少个用来一块异步函数的令人抓狂的技艺,同一时间防止我们陷入深档案的次序的回调嵌套之中。

而外出示一些演示,小编还介绍了 jQuery 3 在同原生 promises 互操作性上所做的更正。尽管大家重申了 jQuery 的老版本同ECMAScript二零一五 在 Promises 落成上有多数不风流罗曼蒂克,Deferred目的仍是您工具箱里意气风发件强有力的工具。作为三个职业开拓人士,当项目标复杂度扩充时,你会发觉它总能派上用场。

打赏扶助作者翻译更加的多好小说,多谢!

打赏译者

接下来,Promise对象有一个then方法,能够用来钦点回调函数。黄金时代旦非同步操作完毕,就调用内定的回调函数。

打赏支持自身翻译愈来愈多好文章,多谢!

任选意气风发种支付办法

图片 1 图片 2

1 赞 5 收藏 评论

复制代码 代码如下:

有关小编:HansDo

图片 3

游走于Web前后端,一向在野门路上寻找着。对油画和数学力不胜任(・-・*),尽其所能做贰个劳动者。 个人主页 · 笔者的稿子 · 18 ·    

图片 4

promise.then(function (content) {
  console.log(content)
})

能够将地方两段代码合併起来,那样程序的流程看得更通晓。

复制代码 代码如下:

get(' (content) {
  console.log(content)
})

在1.7版在此以前,jQuery的Ajax操作使用回调函数。

复制代码 代码如下:

$.ajax({
    url:"/echo/json/",
    success: function(response)
    {
       console.info(response.name);
    }
});

1.7版之后,Ajax操作直接回到Promise对象,那代表能够用then方法钦赐回调函数。

复制代码 代码如下:

$.ajax({
    url: "/echo/json/",
}).then(function (response) {
    console.info(response.name);
});

deferred对象的措施

$.deferred()方法

功用是生成三个deferred对象。

复制代码 代码如下:

var deferred = $.deferred();

done() 和 fail()

这么些章程都用来绑定回调函数。done()内定非同步操作成功后的回调函数,fail()钦定失败后的回调函数。

复制代码 代码如下:

var deferred = $.Deferred();
deferred.done(function(value) {
   alert(value);
});

它们重回的是原本的deferred对象,由此得以行使链式写法,在后面再链接其余办法(包含done和fail在内)。

resolve() 和 reject()

那多少个方法用来更改deferred对象的境况。resolve()将状态改为非同步操作成功,reject()改为操作战败。

复制代码 代码如下:

var deferred = $.Deferred();
deferred.done(function(value) {
   alert(value);
});
deferred.resolve("hello world");

比如调用resolve(),就能相继履行done()和then()方法内定的回调函数;风度翩翩旦调用reject(),就能够相继推行fail()和then()方法钦赐的回调函数。

state方法

该方法用来回到deferred对象近期的景况。

复制代码 代码如下:

var deferred = new $.Deferred();
deferred.state();  // "pending"
deferred.resolve();
deferred.state();  // "resolved"

该办法的重回值有多个:

1.pending:表示操作还一向不完成。
2.resolved:表示操作成功。
3.rejected:表示操作失败。

notify() 和 progress()

progress()用来钦定多个回调函数,当调用notify()方法时,该回调函数将实施。它的盘算是提供一个接口,使得在非同步操作试行进程中,能够施行有些操作,比如准期回去进度条的快慢。

复制代码 代码如下:

 var userProgress = $.Deferred();
    var $profileFields = $("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();
        }
    });

then()

then()的成效也是内定回调函数,它能够选用多个参数,也便是多少个回调函数。第三个参数是resolve时调用的回调函数,第一个参数是reject时调用的回调函数,第多个参数是progress()方法调用的回调函数。

复制代码 代码如下:

deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

在jQuery 1.8事先,then()只是.done().fail()写法的语法糖,三种写法是等价的。在jQuery 1.8之后,then()重临三个新的deferred对象,而done()重临的是本来的deferred对象。如果then()钦定的回调函数有再次来到值,该重临值会作为参数,传入前边的回调函数。

复制代码 代码如下:

var defer = jQuery.Deferred();
defer.done(function(a,b){
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
});
defer.resolve( 2, 3 );

在jQuery 1.8版本在此之前,下面代码的结果是:

复制代码 代码如下:

result = 2
result = 2
result = 2

在jQuery 1.8本子之后,重返结果是

复制代码 代码如下:

result = 2
result = 6
result = NaN

那或多或少索要特别引起注意。

复制代码 代码如下:

$.ajax( url1, { dataType: "json" } )
.then(function( data ) {
    return $.ajax( url2, { data: { user: data.userId } } );
}).done(function( data ) {
  // 从url2获得的数目
});

上面代码最后那三个done方法,管理的是从url2赢得的多寡,实际不是从url1获取的多寡。

使用then()会改进重返值这几个特点,大家得以在调用别的回调函数以前,对前一步操作再次来到的值进行拍卖。

复制代码 代码如下:

var post = $.post("/echo/json/")
    .then(function(p){
        return p.firstName;
    });
post.done(function(r){ console.log(r); });

地点代码先使用then()方法,从重返的数额中抽出所须要的字段(firstName),所从前边的操作就可以只处理那些字段了。

不经常候,Ajax操作重回json字符串里面有多个error属性,表示发生错误。那年,守旧的不二诀要只好是经过done()来推断是不是产生错误。通过then()方法,能够让deferred对象调用fail()方法。

复制代码 代码如下:

var myDeferred = $.post('/echo/json/', {json:JSON.stringify({'error':true})})
    .then(function (response) {
            if (response.error) {
                return $.Deferred().reject(response);
            }
            return response;
        },function () {
            return $.Deferred().reject({error:true});
        }
    );
myDeferred.done(function (response) {
        $("#status").html("Success!");
    }).fail(function (response) {
        $("#status").html("An error occurred");
    });

always()

always()也是点名回调函数,不管是resolve或reject都要调用。

pipe方法

pipe方法采纳二个函数作为参数,表示在调用then方法、done方法、fail方法、always方法内定的回调函数以前,先运转pipe方法钦点的回调函数。它平时用来对服务器重回的数据做始发管理。

promise对象

大多景观下,大家不想让客商从外表修改deferred对象的情形。那时,你能够在deferred对象的根基上,重临贰个对准它的promise对象。大家能够把后人领悟成,promise是deferred的只读版,恐怕更易懂地领略成promise是四个对将在达成的任务的承诺。

你能够由此promise对象,为原始的deferred对象增添回调函数,查询它的景色,不过不大概转移它的图景,也正是说promise对象不容许你调用resolve和reject方法。

复制代码 代码如下:

function getPromise(){
    return $.Deferred().promise();
}
try{
    getPromise().resolve("a");
} catch(err) {
    console.log(err);
}

地点的代码会出错,显示TypeError {} 。

jQuery的ajax() 方法重临的正是叁个promise对象。其他,Animation类操作也能够使用promise对象。

复制代码 代码如下:

var promise = $('div.alert').fadeIn().promise();

$.when()方法

$.when()选取多个deferred对象作为参数,当它们整个运维成功后,才调用resolved状态的回调函数,但万生机勃勃在那之中有三个诉讼失败,就调用rejected状态的回调函数。它相当于将八个非同步操作,合併成贰个。

复制代码 代码如下:

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(successFunc, failureFunc);

地点代码表示,要等到几个ajax操作都截至以往,才实行then方法钦定的回调函数。

when方法里面要试行稍稍个操作,回调函数就有多少个参数,对应前边每七个操作的归来结果。

复制代码 代码如下:

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(function (resp1, resp2, resp3){
    console.log(resp1);
    console.log(resp2);
    console.log(resp3);
});

地点代码的回调函数有多少个参数,resp1、resp2和resp3,依次对应前面多少个ajax操作的回来结果。

when方法的另一个作用是,若是它的参数再次来到的不是一个Deferred或Promise对象,那么when方法的回调函数将 立即运营。

复制代码 代码如下:

$.when({testing: 123}).done(function (x){
  console.log(x.testing); // "123"
});

上边代码中钦赐的回调函数,就要when方法后边立时运行。

选拔那性情格,大家能够写多少个具有缓存效果的异步操作函数。也正是说,第三次调用那个函数的时候,将实践异步操作,后边再调用那个函数,将会回到缓存的结果。

复制代码 代码如下:

function maybeAsync( num ) {
  var dfd = $.Deferred();
  if ( num === 1 ) {
    setTimeout(function() {
      dfd.resolve( num );
    }, 100);
    return dfd.promise();
  }
  return num;
}
$.when(maybeAsync(1)).then(function (resp){
  $('#target').append('<p>' + resp + '</p>');
});
$.when(maybeAsync(0)).then(function (resp){
  $('#target').append( '<p>' + resp + '</p>');
});

地点代码表示,假使maybeAsync函数的参数为1,则实施异步操作,不然立即回到缓存的结果。

实例

wait方法

笔者们能够用deferred对象写三个wait方法,表示等待多少皮秒后再举办。

复制代码 代码如下:

$.wait = function(time) {
  return $.Deferred(function(dfd) {
    setTimeout(dfd.resolve, time);
  });
}

运用格局如下:

复制代码 代码如下:

$.wait(5000).then(function() {
  alert("Hello from the future!");
});

改写setTimeout方法

在上边的wait方法的底蕴上,还足以改写setTimeout方法,让其回来三个deferred对象。

复制代码 代码如下:

function doSomethingLater(fn, time) {
  var dfd = $.Deferred();
  setTimeout(function() {
    dfd.resolve(fn());
  }, time || 0);
  return dfd.promise();
}
var promise = doSomethingLater(function (){
  console.log( '已经推迟试行' );
}, 100);

自定义操作使用deferred接口

咱俩能够运用deferred接口,使得自便操作都得以用done()和fail()钦点回调函数。

复制代码 代码如下:

Twitter = {
  search:function(query) {
    var dfr = $.Deferred();
    $.ajax({
     url:"",
     data:{q:query},
     dataType:'jsonp',
     success:dfr.resolve
    });
    return dfr.promise();
  }
}

应用方式如下:

复制代码 代码如下:

Twitter.search('intridea').then(function(data) {
  alert(data.results[0].text);
});

deferred对象的另贰个优势是能够叠合七个回调函数。

复制代码 代码如下:

function doSomething(arg) {
  var dfr = $.Deferred();
  setTimeout(function() {
    dfr.reject("Sorry, something went wrong.");
  });
  return dfr;
}
doSomething("uh oh").done(function() {
  alert("Won't happen, we're erroring here!");
}).fail(function(message) {
  alert(message)
});

你恐怕感兴趣的随笔:

  • jQuery的deferred对象使用详解
  • jQuery Deferred和Promise创立响应式应用程序详细介绍
  • 利用jQuery的deferred对象达成异步按顺序加载JS文件
  • jQuery源码解析-05异步队列 Deferred 使用介绍
  • jQuery $.extend()用法计算
  • jQuery插件开垦的两种办法及$.fn.extend的详解
  • jQuery.extend 函数详解
  • 原生js达成复制对象、增添对象 相同jquery中的extend()方法
  • jQuery.extend()的兑现格局详解及实例
  • jQuery中的deferred对象和extend方法详解

本文由设计建站发布,转载请注明来源:jQuery的Deferred对象概述,jQuery之Deferred对象详解