I saw this series of articles "Writing a JavaScript asynchronous calling framework 1,2,3,4,5,6" on the Internet two days ago.
Asynchronous operations may produce events in an unexpected order. This problem has been encountered before. I didn't think too much at the time, that is, directly multi-level nesting (nesting the next event after ajax returns) to solve it.
Read it carefully. I was dizzy watching it, and I have to say that my basic knowledge may not be very good, and my grasp of the overall situation is not good either. d Anyway, I find it difficult to understand, and I don’t think it is convenient enough to call.
If it is called like this:
var chain = Async.go(0);
chain
.next(function(){setTimeout("alert(1)", 3000)})
.next(function(){setTimeout("alert(2)",3000)})
.next(function(){setTimeout("alert(3)",3000)}) ;
I think this is perfect. But in fact, if it is an asynchronous call, it is like this:
var chain = Async.go(0);
chain.next(function(){
var operation = new Async.Operation( );
setTimeout(function(){ operation.yield("hello"); }, 3000);
return operation;
});
Of course the last article mentioned it again By encapsulating it, I think this inconvenient call can be generally solved.
Actually, I have had this idea before, which is to find a class or something that can be triggered in my order. When I ask in the group whether there is such a class, others always say Reply to the sentence, just execute it in onreadychange, some even laugh at it! Since I was a newbie at the time, I gave up. And now, although I am still a rookie, I have finally traveled a long way. Just try to write an event queue according to your own understanding.
I am always used to talking by looking at the code, so I will start with the code and then talk about my ideas:
/**
KEQueue —— Events Queue
@Author ake by 2010-04-25
http://www.cnblogs.com/akecn
@param data Each event in the event queue will Pass this parameter as the first parameter unless its value is modified via KEQueue.status.
@method next(Function) The next event to be executed.
@method wait(Number) Wait for a certain period of time before executing the next event.
@method sleep() stops the execution of the event sequence.
@method wake() continues the sequence of events.
**/
var KEQueue = function(data) {
this.staticQueue = [];
this.asyncQueue = [ ];
this.status = "running";
this.result = data;
return this;
}
KEQueue.prototype = {
next:function(callback, async ) {//Add a method
if(!!async) {
this.staticQueue.push("async");//If it is an asynchronous method (a method with a delay effect), add a flag
this.asyncQueue.push(callback);//Storage array for delayed methods
}else {
this.staticQueue.push(callback);//Storage array for directly triggered methods
}
return this;
},
wait:function(delay) {//Delay execution sequence
var self = this;
this.next(function() {//Simulate adding a Delay method
setTimeout(function() {
self.wake.call(self)
}, delay);
},true);
return this;
},
go:function() {//Execute events in the order in which they are added
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();
}
}
I guess you already understand it after reading the code. How to do it, the code is also very simple.
In fact, it is a loop to execute the method in an array. If the array is not a function, the queue operation will be stopped until it is woken up (wake()). The method of use is also more inclined to the way I like.
Of course, maybe I just saw that the events were executed in the order I added them, but there are many other situations or reasons that I didn't expect. If you have suggestions or comments, please leave a message!
The following are usage examples.
//예제 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; //다음으로 변경 pass 수정되지 않은 경우 데이터는 마지막 이벤트
o.wake(); //시퀀스를 수동으로 깨워야 합니다
},2000), true). (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: 밤에 잠자리에 들었을 때 갑자기 이런 말을 하고 싶었습니다. 복잡한 이벤트를 추가하면 모두 시간이 오래 걸리면 예상치 못한 일련의 이벤트가 발생합니까? 각 이벤트가 결국 비동기 이벤트로 처리되어야 한다면 이 대기열은 기껏해야 이벤트 순서를 정렬하는 데 큰 의미가 없을 것입니다. .
아침에 회사로 가는 길에 자바스크립트가 단일 스레드로 작동하고 이벤트가 차단된다는 사실이 문득 생각났습니다. 멀티 스레드라면 그런 대기열을 만들 필요가 없을 것입니다. .
방금 데모를 작성해서 사용해 보았는데 괜찮은 것 같습니다.