js下写一个事件队列操作函数
js下写一个事件队列操作函数
发布时间:2016-12-30 来源:查字典编辑
摘要:前两天在网上看到这一系列的文章《写一个JavaScript异步调用框架1,2,3,4,5,6》。异步操作可能会产生你不希望的事件触发顺序。这...

前两天在网上看到这一系列的文章《写一个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教程学习
编程开发子分类