<body>
<h3>设计模式知识连载(44)---等待者模式:</h3>
<p>
通过对多个异步进程监听,来触发未来发生的动作
</p>
<hr>
<script type="text/javascript">
/**
* 案例一:接口拆分,方式一:初始
*/
// 等待者对象
var Waiter = function() {
// 注册了等待对象容器
var dfd = [] ;
// 成功回调方法容器
var doneArr = [] ;
// 失败回调方法容器
var failArr = [] ;
// 缓存Array方法slice
var _slice = Array.prototype.slice ;
// 保存当前等待者对象
var that = this ;
// 监控对象类
var Primise = function() {
// 监控对象是否解决成功状态
this.resolved = false ;
// 监控对象是否解决失败状态
this.rejected = false ;
}
// 监控对象类原型方法
Primise.prototype = {
// 解决成功
resolve : function() {
// 设置当前监控对象解决成功
this.resolved = true ;
// 如果没有监控对象则取消执行
if(!dfd.length) {
return ;
}
// 遍历所有注册了的监控对象
for(var 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 Primise() ;
}
// 回调执行方法
function _exec(arr){
var i = 0 ;
var len = arr.length ;
// 遍历回调数组执行回调
for(; i < len; i++) {
try {
// 执行回调函数
arr[i] && arr[i]() ;
}catch(e) {
}
}
}
// 监控异步方法 参数:监控对象
that.when = function() {
// 设置监控对象
dfd = _slice.call(arguments) ;
// 获取监控对象数组长度
var i = dfd.length ;
// 向前遍历监控对象,最后一个监控对象的索引值为length-1
for(--i; i >= 0; i--) {
// 如果不存在监控对象,或者监控对象已经解决,或者不是监控对象
if(!dfd[i] || dfd[i].resolved || dfd[i].rejected || !dfd[i] instanceof Primise) {
// 清理内存,清除当前监控对象
dfd.splice(i, 1) ;
}
}
// 返回等待者对象
return that ;
}
// 解决成功回调函数添加方法
that.done = function() {
// 向成功回调函数容器中添加回调方法
doneArr = doneArr.concat(_slice.call(arguments)) ;
// 返回等待者对象
return that ;
}
// 解决失败回调函数添加方法
that.fail = function() {
// 向失败回调函数容器中添加回调方法
failArr = failArr.concat(_slice.call(arguments)) ;
// 返回等待者对象
return that ;
}
}
// 测试用例:
// 创建一个等待者对象
var waiter = new Waiter() ;
// 第一个彩蛋,3秒停止
var first = (function() {
// 创建监听对象
var dtd = waiter.Deferred() ;
setTimeout(function() {
console.log('first finish') ;
// 发布解决成功问题
dtd.resolve() ;
// 发布解决失败问题
// dtd.reject() ;
}, 3000) ;
// 返回监听对象
return dtd ;
})() ;
// 第二个彩蛋,6秒后停止
var second = (function() {
// 创建简体你对象
var dtd = waiter.Deferred() ;
setTimeout(function() {
console.log('second finish') ;
// 发布解决成功消息
dtd.resolve() ;
// 发布解决失败问题
// dtd.reject() ;
}, 6000) ;
// 返回监控对象
return dtd ;
})() ;
// 监听两个彩蛋的工作状态,并执行相应的成功回调函数与失败回调函数
waiter
// 监听两个彩蛋
.when(first, second)
// 添加成功回调函数
.done(function() {
console.log('success') ;
}, function() {
console.log('success again') ;
})
// 添加失败回调函数
.fail(function() {
console.log('fail') ;
}) ;
/**
* 案例二:封装异步请求,方式一:初始
*/
// 封装get请求
var ajaxGet = function(url, success, fail) {
var xhr = new XMLHttpRequest() ;
// 创建监测对象
var dtd = waiter.Deferred() ;
xhr.onload = function(event) {
// 请求成功
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
success && success() ;
// 请求失败
}else {
dtd.reject() ;
fail && fail() ;
}
} ;
xhr.open('get', url, true) ;
xhr.send(null) ;
}
/**
* 案例三:轮询,方式一:初始
*/
// 长轮询
(function getAjaxData() {
// 保存当前函数
var fn = arguments.callee ;
setTimeout(function() {
$.get('./test.php', function() {
console.log('轮询一次') ;
// 再一次执行轮询
fn() ;
}) ;
}, 5000) ;
})() ;
</script>
</body>
设计模式知识连载(44)---等待者模式:
最新推荐文章于 2022-05-29 22:13:30 发布