博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
读jQuery之二十(Deferred对象)
阅读量:5951 次
发布时间:2019-06-19

本文共 3883 字,大约阅读时间需要 12 分钟。

Deferred对象是由 jQuery.Deferred 构造的,jQuery.Deferred 被实现为。

它用来解决JS中的异步编程,它遵循 规范。实现此规范的还有  和 。

 

$.Deferred作为新特性首次出现在版本中,这个版本利用Deferred又完全重写了Ajax模块。

$.Deferred在jQuery代码自身四处被使用,分别是方法、、模块、模块。

这里以版本1.8.3分析,由于后从Deferred中抽离出去了,目前版本的deferred.js代码不过150行,而真正$.Deferred的实现只有100行左右。

 

给$上挂了两个方法,如下

jQuery.extend({	Deferred: function( func ) {		var tuples = [				// action, add listener, listener list, final state				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],				[ "notify", "progress", jQuery.Callbacks("memory") ]			],		...		// All done!		return deferred;	},	// Deferred helper	when: function( subordinate /* , ..., subordinateN */ ) {		var i = 0,			resolveValues = core_slice.call( arguments ),			length = resolveValues.length,			....		return deferred.promise();	}});

 

$.Deferred的实现

  1. 创建三个$.Callbacks对象,分别表示成功,失败,处理中三种状态
  2. 创建了一个promise对象,具有state、always、then、primise方法
  3. 通过扩展primise对象生成最终的Deferred对象,返回该对象

 

$.when的实现

  1. 接受若干个对象,参数仅一个且非Deferred对象将立即执行回调函数
  2. Deferred对象和非Deferred对象混杂时,对于非Deferred对象remaining减1
  3. Deferred对象总数 = 内部构建的Deferred对象 + 所传参数中包含的Deferred对象
  4. 所传参数中所有Deferred对象每当resolve时remaining减1,直到为0时(所有都resolve)执行回调

 

这就是$.Deferred和$.when的全部了,各个方法及使用稍后介绍。

代码阅读中会发现then和when方法的实现最难理解,看多次,后感回味无穷,非常巧妙。then内部会用到不同寻常的递归,when用到了计数,每次异步成功后减一,直到为0后表示全部异步操作成功,这时才可执行回调。

 

上面提到Deferred里有3个$.Callbacks的实例,Deferred自身则围绕这三个对象进行更高层次的抽象。以下是Deferred对象的核心方法

  • done/fail/progress 是 ,将回调函数存入
  • resolve/reject/notify 是 ,执行回调函数(或队列)

 

下面举一些示例看看如何使用Deferred对象。

 

一、done/resolve

function cb() {	alert('success')}var deferred = $.Deferred()deferred.done(cb)setTimeout(function() {	deferred.resolve()}, 3000)

在HTTP中表示后台返回成功状态(如200)时使用,即请求成功后可执行成功回调函数。

 

二、fail/reject

function cb() {	alert('fail')}var deferred = $.Deferred()deferred.fail(cb)setTimeout(function() {	deferred.reject()}, 3000)

在HTTP中表示后台返回非成功状态时使用,即请求失败后可执行失败回调函数。

 

三、progress/notify

function cb() {	alert('progress')}var deferred = $.Deferred()deferred.progress(cb)setInterval(function() {	deferred.notify()}, 2000)

在HTTP中表示请求过程中使用,即请求过程中不断执行回调函数。这可用在文件上传时的loading百分比或进度条。

 

四、链式操作

function fn1() {	alert('success')}function fn2() {	alert('fail')}function fn3() {	alert('progress')}var deferred = $.Deferred()deferred.done(fn1).fail(fn2).progress(fn3) // 链式操作setTimeout(function() {	deferred.resolve()	//deferred.reject()	//deferred.notify()}, 3000)

这样可以很方便了添加成功,失败,进度回调函数。

 

五,便利函数then,一次添加成功,失败,进度回调函数

function fn1() {	alert('success')}function fn2() {	alert('fail')}function fn3() {	alert('progress')}var deferred = $.Deferred()deferred.then(fn1, fn2, fn3)

调用then后还可以继续链式调用then添加多个不同回调函数,这个then也正是jQuery对  的实现。

 

六、使用always方法为成功,失败状态添加同一个回调函数

var deferred = $.Deferred()deferred.always(function() {	var state = deferred.state() 	if ( state === 'resolved') {		alert('success')	} else if (state === 'rejected') {		alert('fail')	}})setTimeout(function() {	deferred.resolve()	//deferred.reject()}, 3000)

回调函数中可以使用deferred.state方法获取异步过程中的最终状态,这里我调用的是deferred.resolve,因此最后的状态是resolved,表示成功。

 

七、when方法保证多个异步操作全部成功后才回调

function fn1() {	alert('done1')}function fn2() {	alert('done2')}function fn3() {	alert('all done')}var deferred1 = $.Deferred()var deferred2 = $.Deferred()deferred1.done(fn1)deferred2.done(fn2)$.when(deferred1, deferred2).done(fn3)setTimeout(function() {	deferred1.resolve()	deferred2.resolve()}, 3000)

先后弹出了done1、done2、all done。 如果setTimeout中有一个reject了,fn3将不会被执行。

 

八、deferred.promise()方法返回只能添加回调的对象,这个对象与$.Deferred()返回的对象不同,只能done/fail/progress,不能resolve/reject/notify。即只能调用callbacks.add,没有callbacks.fire。它是正统Deferred对象的阉割版。

 

 

有了Deferred,我们使用jQuery书写ajax的风格可以这样了

$.ajax(url) .done(success) .progress(handling) .fail(fail)

 

看似和以前比较也没什么优点,但它还可以添加多个回调

$.ajax(url) .done(success1) .done(success2) .fail(fail2) .fail(fail2)

1.5之前的则不行

 

如果多个请求完成后才算成功,1.5之前的是无法解决的,现在则可以用$.when搞定

var ajax1 = $.ajax(url1)var ajax2 = $.ajax(url2)$.when(ajax1, ajax2).done(success)

 

如果项目中有一些异步问题不妨用用Derferred。

 

相关:

 

转载地址:http://dsixx.baihongyu.com/

你可能感兴趣的文章
gnome 桌面 右击 open terminal 失效处理
查看>>
每天一个linux命令(58):rcp命令
查看>>
再论三层架构
查看>>
nginx代理多次302(nginx Follow 302)
查看>>
Jquery教程 1.jquery的基础选择器
查看>>
我的友情链接
查看>>
Highcharts和Hinghstock图表构造参数常用属性
查看>>
模糊测试工具Simple Fuzzer
查看>>
RabbitMQ入门(六) —— 持久化
查看>>
iOS12系统应用发送邮件中的附件
查看>>
我的友情链接
查看>>
LFS学习中遇到的错误
查看>>
lnmp安装脚本
查看>>
Yarn流程、Yarn与MapReduce 1相比
查看>>
SANS:2016年网络威胁情报现状调研报告
查看>>
xlsx格式Excel的处理
查看>>
mysql create database 指定utf-8编码
查看>>
maven 生成可执行的jar的多种方式
查看>>
VS2005访问数据库超时
查看>>
iOS 开发百问(2)
查看>>