等待者模式
等待者模式
等待者模式是通过对多个异步任务进行监听,当异步任务完成后触发未来发生的动作,在没有Promise 这个模型的时候,其实就已经出现这样类似的技术方案,不同的只是没有定制为一个技术规范,等待者模式不属于一般定义的23 种设计模式的范畴,而通常将其看作广义上的技巧型设计模式。
基本介绍
等待者模式就是通过对异步进程监听,来触发未来发生的动作,举个例子当异步进程操作A、B需要都完成以后才能进行C 进程操作,在开发中经常会这样,需要等到上个操作完成或者知道上个操作完成才去触发下个操作,而JavaScript 又是单线程的,不能采用阻塞的方式去处理,在Promise 规范出现之前通常都是使用回调的方式实现,这样很容易造成回调地狱,等待者模式就是在Promise规范制定之前一个类似于Promise 的解决方案,可以算是Promise规范的一个参考前身。
实现
function Waiter() {
let dfd = [] // 等待对象容器
let doneArr = [] // 成功回调容器
let failArr = [] // 失败回调容器
// 监控对象类
const Promise = function () {
this.resolved = false // 监控对象是否解决成功状态
this.rejected = false // 监控对象是否解决失败状态
}
Promise.prototype = {
// 解决成功
resolve() {
this.resolved = true // 设置当前监控状态是成功
if (!dfd.length)
return void 0
for (let i = dfd.length - 1; i >= 0; i--) {
// 对象监控对象遍历如果任一个对象没有解决或者失败就返回
if (dfd[i] && !dfd[i].resolved || dfd[i].rejected)
return void 0
dfd.splice(i, 1)
}
_exec(doneArr)
},
// 解决失败
reject() {
this.rejected = true // 设置当前监控状态是失败
if (!dfd.length)
return void 0 // 没有监控对象取消
dfd.splice(0) // 清除监控对象
_exec(failArr)
}
}
this.Deferred = function () {
return new Promise()
}
// 回调执行方法
function _exec(arr) {
for (let i = 0, len = arr.length; i < len; i++) {
try {
arr[i] && arr[i]()
}
catch (e) {
// console.warn("Error", e);
_exec(failArr)
}
}
};
// 监控异步方法参数
this.when = function (...args) {
// 设置监控对象
dfd = args
let i = args.length
// 向前遍历监控对象
for (--i; i >= 0; i--) {
// 不存在监控对象 监控对象已经解决 监控对象失败
if (!args[i] || args[i].resolved || args[i].rejected || !args[i] instanceof Promise) {
args.splice(i, 1)
}
}
return this // 返回等待者对象
}
// 解决成功回调函数添加方法
this.done = function (...args) {
doneArr = doneArr.concat(args) // 向成功毁掉函数容器中添加回调方法
return this
}
// 解决失败回调函数添加方法
this.fail = function (...args) {
failArr = failArr.concat(args) // 向失败回调函数中添加方法
return this
}
}(function () {
const waiter = new Waiter() // 创建一个等待者实例
const first = (function () {
const promise = waiter.Deferred()
setTimeout(() => {
promise.resolve()
}, 1000)
return promise // 返回监听这对象
}())
const second = (function () { // 第二个对象
const promise = waiter.Deferred()
setTimeout(() => {
promise.resolve()
}, 2000)
return promise
}())
waiter.when(first, second).done(() => {
console.log('success')
}).fail(() => {
console.log('fail')
})
})()
;(function () {
const waiter = new Waiter() // 创建一个等待者实例
const first = (function () {
const promise = waiter.Deferred()
setTimeout(() => {
promise.resolve()
}, 1000)
return promise // 返回监听这对象
}())
const second = (function () { // 第二个对象
const promise = waiter.Deferred()
setTimeout(() => {
promise.resolve()
}, 3000)
return promise
}())
waiter.when(first, second).done(() => {
throw new Error('test')
}).fail(() => {
console.log('fail')
})
})()Promise
Promise就是异步操作的一个解决方案,用于表示一个异步操作的最终完成或失败及其结果值,Promise有各种开源实现,在ES6 中被统一规范,由浏览器直接支持。上面我们实现的等待者模式更类似于Promise.all()。
示例
这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise 对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise 对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise 返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable 里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。
const p1 = new Promise((resolve, reject) => {
resolve('success1')
})
const p2 = new Promise((resolve, reject) => {
resolve('success2')
})
const p3 = new Promise((resolve, reject) => {
reject('fail')
})
Promise.all([p1, p2]).then((result) => {
console.log(result) // 成功状态 // ["success1", "success2"]
}).catch((error) => {
console.log(error)
})
Promise.all([p1, p3, p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败状态 // fail
})更新日志
16e12-于a3cca-于c0f2d-于e6a79-于
