摘要:比较下和也就是说返回值是的一个非状态操作的子集,允许我们添加回调,但是不允许我们操作的状态。前面说了的返回值是一个新的对象,如果在新的对象上继续添加回调会怎么样呢我们分两种情况来看。方法的返回值不是对象的返回值会传递给的参数。
前言
Deferred是从1.5版本引入的一个核心特性之一,主要是为了解决Callback Hell,老生常谈的问题,这里就不多赘述了。本文旨在剖析Deferred的内部实现,让大家能够深入了解Deferred。
API $.Deferred通过调用$.Deferred()获取到一个Deferred实例,如下
var dd = $.Deferred();
调用的时候可以传入一个函数(可以简单的看作构造函数),如下
var dd = $.Deferred(function (newDefer) { newDefer.name = "My Deferred"; }); console.log(dd.name);//My Deferredresolve/done reject/fail notify/progress
Deferred的实现使用了闭包,内部维护了三个$.Callbacks管理队列。
可以说Deferred的核心在于$.Callbacks。如果不熟悉$.Callbacks的请自行搜索或参考我的另一篇介绍文章jQuery Callbacks。代码可以简化成下面的样子
var resolveCb = jQuery.Callbacks("once memory"); var rejectCb = jQuery.Callbacks("once memory"); var notifyCb = jQuery.Callbacks("memory"); done = resolveCb.add resolve ~ resolveCb.fire resolveWith = resolveCb.fireWith fail = rejectCb.add reject ~ rejectCb.fire rejectWith = rejectCb.fireWith progress = notifyCb.add notify ~ notifyCb.fire notifyWith = notifyCb.fireWith
~表示可以简单理解为对等。我们再看看下面的代码会不会有不一样的感觉了
var dd = $.Deferred(); dd.done(function (name) { console.log(name, 1); }).done(function (name) { console.log(name, 2); }); dd.resolve("Jacky");
其实就相当于
resolveCb.add(function (name) { console.log(name, 1); }).add(function (name) { console.log(name, 2); }); resolveCb.fire("Jacky");
当Deferred执行完resolve以后,同时会调用rejectCb.disable和notifyCb.lock。
当Deferred执行完reject以后,同时会调用resolveCb.disable和notifyCb.lock。
notifyCb就是一个单纯的$.Callbacks,但是它的状态会受到resolve/reject的影响。
resolve/resolveWith reject/rejectWith notify/notifyWithresolveCb和rejectCb两者之间是相互限制的,一旦两者中的某一个fire了,另一个就会被disable。通过这种方式来达到唯一状态。
就是fire和firewith的区别
state返回Deferred的当前状态,总共有三种状态
执行resolve/reject前,返回值是pending
执行了resolve,返回值是resolved
执行了reject,返回值是rejected
var dd = $.Deferred();
console.log(dd.state());//pending
dd.resolve();
console.log(dd.state());//resolved
//dd.reject();
//console.log(dd.state());//rejected
看下源码大家就一清二楚了
还是调用的done和fail,往各自队列里添加回调。
提供Deferred的非状态接口。比较下Deferred和Deferred.promise()
var dd = $.Deferred(); var promise = dd.promise(); console.log(dd); console.log(promise);
也就是说promise返回值是Deferred的一个非状态操作的子集,允许我们添加回调,但是不允许我们操作Deferred的状态。也可以将这些方法添加到某一个对象上,例如
var obj = {name: "xxx"}; var dd = $.Deferred(); var newObj = dd.promise(obj); console.log(newObj); console.log(newObj === obj);then/pipe
pipe是为了向下兼容留下的方法,pipe===then。then支持三个参数,返回值是一个新的promise对象。看几个例子
例子一var dd = $.Deferred(); dd.done(function (name) { console.log("dd", name); }); dd.then(function (name) { console.log("then", name); }); dd.resolve("Jacky"); //dd Jacky //then Jacky例子二
var dd = $.Deferred(); dd.fail(function (name) { console.log("dd", name); }); dd.then(null, function (name) { console.log("then", name); }); dd.reject("Jacky"); //dd Jacky //then Jacky例子三
var dd = $.Deferred(); dd.progress(function (name) { console.log("dd", name); }); dd.then(null, null, function (name) { console.log("then", name); }); dd.notify("Jacky"); //dd Jacky //then Jacky
三个参数刚好分别添加到了内部的三个回调队列中。dd.then(fn)可以简单看作dd.done(fn)。前面说了then的返回值是一个新的promise对象,如果在新的Deferred对象上继续添加回调会怎么样呢?我们分两种情况来看。
then方法的返回值不是Deferred对象var dd = $.Deferred(); var newdd = dd.then(function (name) { console.log("then", name); return "Mary"; }); newdd.done(function (name) { console.log("newDefer", name); }); dd.resolve("Jacky"); //then Jacky //newDefer Mary
then的返回值会传递给done/fail的参数。而且无需我们手动调用newdd.resolve,内部帮我们调用了
返回值是Deferred对象看个例子
var dd = $.Deferred(); var returndd = $.Deferred();
var newdd = dd.then(function (name) { console.log("then", name); return returndd; }); newdd.done(function (name) { console.log("newDefer", name); }); dd.resolve("Jacky");//then Jacky
newdd.done添加的函数没有马上执行了。我们手动调用下returndd.resolve
var dd = $.Deferred(); var returndd = $.Deferred();
var newdd = dd.then(function (name) { console.log("then", name); return returndd; }); newdd.done(function (name) { console.log("newDefer", name); }); dd.resolve("Jacky");//then Jacky returndd.resolve("Helen");//newDefer Helen
这里就是我们的promise编程了
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78538.html
摘要:中文文档简单说,对象就是的回调函数解决方案。为了让回调函数的名字统一,便于在中使用。普通操作的回调函数接口对象的最大优点,就是它把这一套回调函数接口,从操作扩展到了所有操作。指定操作成功时的回调函数。 参考链接 jQuery API中文文档 jQuery.Deferred jQuery.when jQuery的deferred对象详解 jQuery deferred 对象的 prom...
摘要:通常的做法是,为它们指定回调函数。指定操作成功时的回调函数指定操作失败时的回调函数没有参数时,返回一个新的对象,该对象的运行状态无法被改变接受参数时,作用为在参数对象上部署接口。 jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本。 每个版本都会引入一些新功能。今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象。 这个功...
摘要:和和都有和,但是略有不同。实际上返回的是一个对象。和添加的回调,添加的回调。所以在调用成功的情况下执行添加的回调,调用失败时执行添加的回调。,产生对象并,产生对象并,然后继续处理,的语法糖,和的差不多但不同。 Deferred 和 Promise ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不过它们的作用可以简单的用两句话来描述 Deffere...
摘要:通常的做法是,为它们指定回调函数。简单说,对象就是的回调函数解决方案。指定操作成功时的回调函数指定操作失败时的回调函数没有参数时,返回一个新的对象,该对象的运行状态无法被改变接受参数时,作用为在参数对象上部署接口。 转自:阮一峰:http://www.ruanyifeng.com/blo... 一、什么是deferred对象?开发网站的过程中,我们经常遇到某些耗时很长的javascri...
摘要:回调队列对象,用于构建易于操作的回调函数集合,在操作完成后进行执行。对象对象,用于管理回调函数的多用途列表。如果传入一个延迟对象,则返回该对象的对象,可以继续绑定其余回调,在执行结束状态之后也同时调用其回调函数。 在工作中我们可能会把jQuery选择做自己项目的基础库,因为其提供了简便的DOM选择器以及封装了很多实用的方法,比如$.ajax(),它使得我们不用操作xhr和xdr对象,直...
摘要:我们称为回调对象,它内部会维护一个数组,我们可以向其中添加若干个回调函数,然后在某一条件下触发执行。第一次之后,再次新的回调函数时,自动执行回调。当前面的回调函数返回时,终止后面的回调继续执行。 最近懒癌发作,说好的系列文章,写了一半,一直懒得写,今天补上一篇。 Deferred 我们在使用promise对象时,总会提到一个与它关系密切的对象——Deferred。其实Deferred没...
阅读 1891·2021-11-23 09:51
阅读 1534·2021-11-19 09:40
阅读 3207·2021-11-11 11:01
阅读 1104·2021-09-27 13:34
阅读 1834·2021-09-22 15:56
阅读 2121·2019-08-30 15:52
阅读 1060·2019-08-30 14:13
阅读 3472·2019-08-30 14:10