js下写一个事件队列操作函数


Posted in Javascript onJuly 19, 2010

前两天在网上看到这一系列的文章《写一个JavaScript异步调用框架1,2,3,4,5,6》。

异步操作可能会产生你不希望的事件触发顺序。这个问题以前也遇到过,当时没想太多,也就是直接多层嵌套(在ajax返回以后嵌套下一个事件)来解决。

认真的看了一遍。看的头昏,不得不说我可能基础并不好,在大局上的掌握也不好。d反正我是觉得很难理解,也不觉得它的调用时够方便的。

 如果是这么调用:

var chain = Async.go(0);
chain
.next(function(){setTimeout("alert(1)",3000)})
.next(function(){setTimeout("alert(2)",3000)})
.next(function(){setTimeout("alert(3)",3000)});

我觉得这样是完美的。但是实际上如果是异步调用却是要这样:

var chain = Async.go(0);
chain.next(function(){
var operation = new Async.Operation();
setTimeout(function(){ operation.yield("hello"); }, 3000);
return operation;
});

当然最后一篇提到再次封装一下,我想大致上就能解决这种不方便的调用了。

其实以前我也是有过这个念头,就是找一个能按我的顺序来触发的类或者什么,群里问问是否有这种类的时候,别人总都回句,在onreadychange里执行就好啦,甚至有嘲笑的!加上当时又是初学的菜鸟也便作罢了。而现在虽然依旧是菜鸟,但终究飞了一段路程了。就试试按自己的理解写一个事件队列吧。

我总习惯看代码说话,所以先上代码,然后说一下思路好了:

/** 
KEQueue —— Events Queue 
@Author ake by 2010-04-25 
http://www.cnblogs.com/akecn @param data 事件队列中每个事件都会将该参数作为第一个参数传递下去,除非通过KEQueue.status修改它的值。 
@method next(Function) 下一个要执行的事件。 
@method wait(Number) 等待一定时间后执行下一个事件。 
@method sleep() 停止事件序列的执行。 
@method wake() 继续执行事件序列。 
**/ 
var KEQueue = function(data) { 
this.staticQueue = []; 
this.asyncQueue = []; 
this.status = "running"; 
this.result = data; 
return this; 
} 
KEQueue.prototype = { 
next:function(callback, async) {//添加一个方法 
if(!!async) { 
this.staticQueue.push("async");//如果是异步方法(会有延时效果的方法)就添加标识 
this.asyncQueue.push(callback);//延时方法的存放数组 
}else { 
this.staticQueue.push(callback);//直接触发的方法的存放数组 
} 
return this; 
}, 
wait:function(delay) {//延迟执行序列 
var self = this; 
this.next(function() {//模拟添加一个延时方法 
setTimeout(function() { 
self.wake.call(self) 
}, delay); 
},true); 
return this; 
}, 
go:function() {//按事件添加的先后顺序依次执行事件 
if(this.staticQueue.length == 0) return; 
while(this.staticQueue.length > 0) { 
if(this.status === "sleep") return; 
var fun = this.staticQueue.shift(); 
if(typeof fun == "string" && fun == "async") { 
fun = this.asyncQueue.shift(); 
fun(this.result); 
this.sleep(); 
}else { 
fun(this.result); 
} 
} 
}, 
sleep:function() { 
this.status = "sleep"; 
}, 
wake:function() { 
this.status = "running"; 
this.go(); 
} 
}

估计你看了代码就已经明白是怎么做的了,代码也很简单。

其实就是循环去执行一个数组中的方法,如果数组中存放的不是function,就停止队列的操作直到被叫醒(wake())。使用方法也比较偏向我喜欢的方式。

当然也许我只是看到事件是按我添加的顺序去执行了,但有很多其他的情况或者原因没想到。如果您有建议或者意见,欢迎留言!

以下是使用示例。

//示例1 添加事件、执行事件队列 
function show(n) { 
console.log(n); 
} 
var o = new KEQueue("0"); 
o.next(function(d) { //参数是构造时传递的数据。整个事件队列都会返回该数据作为参数。 
show(d + 1); 
}).next(function(d) { 
setTimeout(function() { //模拟延时操作(异步操作) 
show(d + 2); 
o.result = 0; //更改用以传递的数据,如果不修改,该数据会保持一致一直传递到最后一个事件。 
o.wake(); //需要手动唤醒序列 
},2000); 
},true).next(function(d){ 
show(d + 3); 
}).go(); o.next(function(d) { 
setTimeout(function() {show(d + 4);o.wake(); },1000); 
},true).wait(1000) //手动推迟1秒执行下面的方法 
.next(function(d) { 
show(d + 5); 
}).go(); 
//示例2 
o.next(function() { 
show(1); 
}) 
setTimeout(function() { 
o.next(function(){ 
setTimeout(function() { 
show(2); 
o.wake(); 
},2000) 
},true).go(); 
},1000); 
setTimeout(function() { 
o.next(function() { 
show(3); 
}).go(); 
},2000);

PS:晚上睡觉的时候突然想说如果添加的是一个复杂事件,那么所消耗的时间久长了,这样会不会造成不期望的事件顺序呢?如果这样每个事件最后都要显示当做异步事件去处理,那这个队列就没什么大的意义了,最多就是帮你梳理一下事件顺序,仅此而已了。。

早上去公司路上又突然想起,JavaScript是单线程操作的哎,事件会被阻塞的,如果是多线程,估计也不需要做这么个队列了。

刚才写个demo试了一下恩,看来还是没问题的。

Javascript 相关文章推荐
Javascript 获取LI里的内容
Dec 17 Javascript
firefox浏览器不支持innerText的解决方法
Aug 07 Javascript
js防止DIV布局滚动时闪动的解决方法
Oct 30 Javascript
js中使用使用原型(prototype)定义方法的好处详解
Jul 04 Javascript
js制作支付倒计时页面
Oct 21 Javascript
jQuery animate()实现背景色渐变效果的处理方法【使用jQuery.color.js插件】
Mar 15 Javascript
layui表格实现代码
May 20 Javascript
javascript cookie的基本操作(添加和删除)
Jul 24 Javascript
Vue props 单向数据流的实现
Nov 06 Javascript
js中let能否完全替代IIFE
Jun 15 Javascript
js实现二级联动简单实例
Jan 11 Javascript
详解Vue.js 可拖放文本框组件的使用
Mar 03 Vue.js
js+css在交互上的应用
Jul 18 #Javascript
基于jQuery试卷自动排版系统
Jul 18 #Javascript
Date对象格式化函数代码
Jul 17 #Javascript
js下利用控制器载入对应脚本
Jul 17 #Javascript
js 纯数字不重复排列的另类方法
Jul 17 #Javascript
jQuery Autocomplete自动完成插件
Jul 17 #Javascript
一个js拖拽的效果类和dom-drag.js浅析
Jul 17 #Javascript
You might like
天使彦史上最神还原,性别曝光的那一刻,百万网友恋爱了
2020/03/02 国漫
md5 16位二进制与32位字符串相互转换示例
2013/12/30 PHP
分享一个超好用的php header下载函数
2014/01/31 PHP
[原创]php常用字符串输出方法分析(echo,print,printf及sprintf)
2016/07/09 PHP
PHP获取用户客户端真实IP的解决方案
2016/10/10 PHP
总结AJAX相关JS代码片段和浏览器模型
2007/08/15 Javascript
在IE,Firefox,Safari,Chrome,Opera浏览器上调试javascript
2008/12/02 Javascript
JavaScript学习历程和心得小结
2010/08/16 Javascript
JavaScript去掉空格的方法集合
2010/12/28 Javascript
不得不分享的JavaScript常用方法函数集(上)
2015/12/23 Javascript
request请求获取参数的实现方法(post和get两种方式)
2016/09/27 Javascript
Bootstrap提示框效果的实例代码
2017/07/12 Javascript
iframe高度自适应及隐藏滚动条的实例详解
2017/09/29 Javascript
jQuery动态移除与增加onclick属性的方法详解
2018/06/07 jQuery
vue搜索和vue模糊搜索代码实例
2019/05/07 Javascript
vue 对axios get pust put delete封装的实例代码
2020/01/05 Javascript
[02:27]刀塔重生降临
2015/10/14 DOTA
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
基于python爬虫数据处理(详解)
2017/06/10 Python
Python中函数eval和ast.literal_eval的区别详解
2017/08/10 Python
使用pandas批量处理矢量化字符串的实例讲解
2018/07/10 Python
python读取与处理netcdf数据方式
2020/02/14 Python
Python 去除字符串中指定字符串
2020/03/05 Python
Python实现子类调用父类的初始化实例
2020/03/12 Python
在Keras中利用np.random.shuffle()打乱数据集实例
2020/06/15 Python
html5贪吃蛇游戏使用63行代码完美实现
2013/06/25 HTML / CSS
法国高保真音响和家庭影院商店:Son Video
2019/04/26 全球购物
个人求职简历的自我评价
2013/10/19 职场文书
网络工程专业自荐信范文
2014/03/16 职场文书
小学生手册家长评语
2014/04/16 职场文书
电力培训心得体会
2014/09/02 职场文书
实习介绍信模板
2015/01/30 职场文书
团员个人总结
2015/02/26 职场文书
建筑质检员岗位职责
2015/04/08 职场文书
JavaScript最完整的深浅拷贝实现方式详解
2022/02/28 Javascript
HTML5之高度塌陷问题的解决
2022/06/01 HTML / CSS