在Jquery中,对比异步回调函数管理工具方法中的$.Callbacks,还有一个更加方便的管理异步回调函数的工具方法,而且这是一个有状态的方法 — $.Deferred。
如果不了解 $.Callbacks方法,建议先看我上一篇文章Callbacks基本使用
关于$.Deferred
为了更好区分回调函数,jquery内部给Deferred对象定义了三种注册和调用函数的方法:
类型 | 注册 | 调用 |
---|---|---|
成功状态 | $.Deferred.done(fn) | $.Deferred.resolve(参数) |
失败状态 | $.Deferred.fail(fn) | $.Deferred.reject(参数) |
进行状态 | $.Deferred.progress(fn) | $.Deferred.notify(参数) |
本质上done和fail原理是一样的,只是为了通过函数名来更好的区分,成功和失败回调的函数,他们和progress区别就是,progress状态的函数会继续执行异步任务,直到达到done或fail的回调条件为止,而达到done或fail执行条件的时候,会终止当前异步任务。
案例:
<script>
// 回调函数
var master = function(){
console.log('你是最棒的')
}
var good = function(){
console.log('还不错')
}
var loser = function(){
console.log('太差劲了')
}
// 声明deferred对象
var deferred = $.Deferred()
// 注册成功时 触发的函数
deferred.done(master)
// 注册失败时 触发的函数
deferred.fail(loser)
// 注册进行时 触发的函数
deferred.progress(good)
// 通过定时器异步任务,调用不同的回调函数
var timer = setInterval(function(){
var num = Math.random()*100
if(num > 85){
// 成功时 回调
deferred.resolve()
}else if(num < 60){
// 失败时 回调
deferred.reject()
}else{
// 进行时 回调
deferred.notify()
}
},1500)
</script>
以上这种案例 deferred对象是全局的,resolve,reject,notify还是可以被人为的在全局直接调用,因此这是不太合理的。resolve,reject,notify这三个触发函数必须是由某种特定条件才能调用,因此我们需要通过promise方法,只允许外部注册函数,不允许调用函数。
案例改造如下:
<script>
// 回调函数
var master = function(){
console.log('你是最棒的')
}
var good = function(){
console.log('还不错')
}
var loser = function(){
console.log('太差劲了')
}
var asyn = function(){
// 声明deferred对象
var deferred = $.Deferred()
// 通过定时器异步任务,调用不同的回调函数
setInterval(function(){
var num = Math.random()*100
if(num > 85){
// 成功时候调用
deferred.resolve()
}else if(num < 60){
// 失败调用
deferred.reject()
}else{
// 进行中调用
deferred.notify()
}
},1500)
return deferred.promise()
}
//获取promise
var deferred = asyn()
// 注册成功时 触发的函数
deferred.done(master)
// 注册失败时 触发的函数
deferred.fail(loser)
// 注册失败时 触发的函数
deferred.progress(good)
</script>
简化注册函数写法:then
原来:
// 注册成功时 触发的函数
deferred.done(master)
// 注册失败时 触发的函数
deferred.fail(loser)
// 注册进行中的函数
deferred.progress(good)
简化:
//注册顺序为:成功,失败,进行中的函数
deferred.then(master,loser,good)
链式调用then
//形式如:
deferred.then(master,loser,good)
.then(fn1,fn2,fn3)
.then(fn1,fn2,fn3)
链式调用的前提是上个then返回一个promise对象。
案例:
<script>
// 回调函数
var master = function(){
console.log('你是最棒的')
return asyn()
// 成功时 继续执行异步任务 并且返回promise
}
var good = function(){
console.log('还不错')
return asyn()
// 进行时 继续执行异步任务 并且返回promise
}
var loser = function(){
console.log('太差劲了')
return asyn()
// 失败时 继续执行异步任务 并且返回promise
}
var asyn = function(){
// 声明deferred对象
var deferred = $.Deferred()
// 通过定时器异步任务,调用不同的回调函数
setInterval(function(){
var num = Math.random()*100
if(num > 85){
// 成功时候调用
deferred.resolve()
}else if(num < 60){
// 失败调用
deferred.reject()
}else{
// 进行中调用
deferred.notify()
}
},1500)
return deferred.promise()
}
//获取promise
var deferred = asyn()
deferred.then(master,loser,good).then(master,loser,good)
//执行了两次回调
</script>