首页 > 代码库 > Deferred
Deferred
上文中提到了Promise构造函数,就不得不提deferred(延迟)对象了,其实,让deferred对象得到推广的便是其在jQuery中的使用,本文就jQuery中对deferred对象的使用进行探讨。
延迟对象,在jQuery的1.5引入,是通过调用jQuery.Deferred()
方法创建一个可链式调用的工具对象。 它可以注册多个回调到回调队列, 调用回调队列,准备代替任何同步或异步函数的成功或失败状态。
延迟对象是可链式调用的,类似于jQuery对象是可链接的方式, 但它有其自己的方法。 创建一个Deferred(延迟)对象后,你可以通过使用下面任何方法 直接从对象创建或者链式调用 或 保存对象的一个变量,调用该变量的一个或多个方法。
先看看$.Deferred是 什么?
可以看出Deferred只是一个普通函数,没有太多的信息,那我们调用一下试试。
我们又可以看出,其实Deferred函数其实返回的是一个对象,这个对象也有always、catch、done、fail、notity、notifyWith、pipe、promise、progress、reject、rejectWith、resolve、resolveWith、state、then方法。
Deferred有三个状态,pending:未完成,resolved:操作成功,rejected: 操作失败
当deferred1对象调用resolved时,deferred1中的done方法会被调用,当deferred1对象调用rejected时,deferred1的fail方法会被调用,比如
var deferred1 = $.Deferred(); deferred1.done(function (data) { console.log(‘success: ‘, data) }) deferred1.fail(function (err) { console.log(‘err: ‘, err) })
setTimeout(function(){
deferred1.resolve(‘victory‘)
},200)
//输出success: victory
我们接着聊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()方法调用的回调函数。
和谈Promise一样,现在我们也Deferred来封装一个getJSON函数,实现AJAX的例子
var getJSON = function(url) { var deferred = $.Deferred();var client = new XMLHttpRequest(); client.open(‘GET‘, url); client.onreadystatechange = function(){ if (this.readyState !== 4) { return } if (this.status === 200) { deferred.resolve(this.response) } else { deferred.reject(new Error(this.statusText)) } } return deferred } getJSON(‘/db.json‘).then(function(json){ console.log(‘Result:‘, json) }, function(error){ console.log(‘error:‘, error) })
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); }
//会进入catch方法,显示TypeError {}
jQuery的ajax() 方法返回的就是一个promise对象。
Deferred