JS 手动实现Promise
手动实现类Promise
创建等待对象
Waiter
const Waiter = function(){
//等待对象容器
let dfd = []
//成功回掉方法容器
let doneArr = []
//失败回掉方法容器
let failArr = []
/*
存储Array中的slice方法
(slice(start,[end])方法用于切割数组并返回一个新的数组)
*/
const slice = Array.prototype.slice
//存储当前对象
const that = this
const Promise = function(){
//监控对象是否解决成功
this.resolved = false
//监控对象是否解决失败
this.rejected = false
}
Promise.prototype={
//解决成功
resolve:function(){
//设置当前监控对象执行成功
this.resolved = true
//如果没有监控对象则取消执行
if(!dfd.length){
return
}
//遍历所有注册的监控对象
for(let i = dfd.length -1; i >= 0; i--){
//如果有任意—个监控对象设有被解决或者解决失败则返回
if(dfd[i]&&!dfd[i].resolved||dfd[i].rejected){
return
}
//清除监控对象
dfd.splice(i,1)
}
//执行解决成功回调方法
_exec(doneArr)
},
//解决失败
reject:function(){
//设置当前监控对象解决失败
this.rejected = true
//如果设有监控对象则取消执行
if(!dfd.length){
return
}
//清除所有监控对象
dfd.splice(0)
//执行解决失败回调方法
_exec(failArr)
}
}
//创建监控对象
that.Deferred = function(){
return new Promise()
}
//回掉执行方法
function _exec(arr){
for(let i=0;i<arr.length;i++){
try{
arr[i]&&arr[i]()
}catch(error){
console.error(erroe)
}
}
}
//监控异步方法
that.when = function(){
//设置监控对象
dfd = slice.call(arguments)
//想前遍历监控对象,最后一个监控对象的索引值为 length-1
for(let i=dfd.length-1;i>=0;i--){
if(!dfd[i]||dfd[i].resolved||dfd[i].rejected||!dfd[i] instanceof Promise){
dfd.splice(i,1)
}
}
//返回等待着对象(用于链式回调)
return that
}
//解决成功回调函数添加方法
that.done = function(){
//向成功回调函数容器中添加回调方法
doneArr = doneAtrr.concat(slice.call(arguments))
return that
}
//解决失败回调函数添加方法
that.fail = function(){
//向失败回调函数容器中添加回调方法
failArr = failArr.concat(slice.call(arguments))
return that
}
}
demo
const waiter = new Waiter()
const first =function(){
//创建一个Promise监听对象
const dtd = waiter.Deferred()
setTimeout(function(){
console.log('first')
//执行完成标记
dtd.resolve()
},5000)
return dtd
}
const second =function(){
const dtd = waiter.Deferred()
setTimeout(function(){
console.log('second')
//执行完成标记
dtd.resolve()
},10000)
return dtd
}
waiter
//添加监听
.when(first(),second())
//添加成功回调函数
.done(function(){console.log('success')},function(){console.log('success again')})
//添加失败回调函数
.fail(function(){console.log('fail')})
/**
=> first
second
success
success again
*/
参考至 JavaScript设计模式1 中的 等待者模式2 。