0

I tried a long time to figure out, how event and event loop works. I read so many article in internet and books about event registration and event loop, but I still can not imagine how it works.

I am reading the book Async JavaScript from Prgmatic Bookshelft about event queue, you can read in the book an article.

When we call setTimeout, a timeout event is queued. Then execution continues, the code after the setTimeout call runs and so on, until no code more left. After then it will start the event loop and detect, which event get fired and it will call the handler.

After this article, I have got a bit imagination about event and async in Javascript. Then I tried by myself the following code:

setTimeout(function(){alert("Hello")},0);

for (var i = 0; i <= 100000; i++) {
    console.log('I am loop');
}

I have set the time 0, because I want to have confirmation about this sentence:

the code after the setTimeout call runs and so on..

and

After then it will start the event loop and...

until here, everything is fine how event in Javascript; it works. Then I keep continue reading Async JavaScript book, and had read the following:

Input events work the same way: when a user clicks a DOM element with a click handler attached, a click event is queued. But the handler won't be executed until all currently running code had finished.

The first sentence sounds for me a bit confused. For example:

//Some codes
#("element").click(function(e){
    //Do something
});
//Some codes

What I don't understand here is, when the compiler will saved a click event in the event queue? Will it be saved in the queue after registration (after this code) or when I had clicked the element?

In node I tried this code, to figure out how event works. Consider the following code:

var events = require("events");
var event = new events.EventEmitter();

event.on('ev1', function () {
    console.log('Into ev1');

});

event.emit('ev1');
for (var i = 0; i <= 5; i++) {
    console.log('I am in the loop');
}

console.log('I am finish with loop');

What I am expected here is:

I am in the loop
I am in the loop
I am in the loop
I am in the loop
I am in the loop
I am in the loop
I am finish with loop
Into ev1

but what I got it is:

Into ev1
I am in the loop
I am in the loop
I am in the loop
I am in the loop
I am in the loop
I am in the loop
I am finish with loop

After this output, it breaks all my imagination about event (async) execution and event loop that I had read in the book and article in the net before. Consider this sentence in the book:

the code after the setTimeout call runs and so, until no code more left. After then it will start the event loop and detect, which event get fired and it will call the handler.

But why the code above with the EventEmitter works opposite? I thought the event loop will be execute at the end (after other codes be done).

I had read in internet about database (for example mongoose) query with node is async. I don't know how async database query definitively works, but I am imagining like this:

Database request and response

Please explain me, how events in Javascript really work?

4

1 回答 1

1

setTimeout与 有点不同EventEmitter,因此您得到了这些结果。首先,我会要求您先运行这些示例。

将其保存在 async.html 中并在浏览器中运行。检查控制台以查看结果。

<div id="element">
</div>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
setTimeout(function(){console.log("Hello")},0);
$("#element").click(function(e){
    console.log("Inside");
});
$("#element").click();
for (var i = 0; i < 5; i++) {
    console.log('I am loop');
}
</script>

输出

Inside
I am loop
I am loop
I am loop
I am loop
I am loop
Hello

现在将其保存在 async.js 中并在 node.js 中运行

setTimeout(function(){console.log("Hello")},0);

for (var i = 0; i < 5; i++) {
    console.log('I am loop');
}

输出

I am loop
I am loop
I am loop
I am loop
I am loop
Hello

你会发现它setTimeout的工作方式与EventEmitter. EventEmitter 立即执行处理程序,而 setTimeout 尝试立即执行它。直到下一个刻度才会执行这些操作。在这里阅读。

不要将 setTimeout 与 EventEmitter 混用。

编辑

您的示例不能很好地展示异步性。您只是在事件处理程序中运行一个循环。这是一个更清楚的例子:

var events = require("events");
var event = new events.EventEmitter();

event.on("work", function (i,cb) {
    console.log('Started '+i );
    setTimeout(function(){event.emit("done",i,cb);},Math.random()*1000);
});

event.on("done", function (i,cb) {
    cb(i);
});

var async = function (cb) {
    for (var i = 0; i <= 100; i++) {
        emitclosure(i,cb);
    }
}

function emitclosure(i,cb){
        setTimeout(function(){event.emit("work",i,cb)},Math.random()*1000);
}

async(function (i) {
    console.log("I have done "+i);
});

我要指出,我setTimeout与事件一起使用只是为了给人一种工作到达延迟和处理延迟的感觉,这与问题中的同义词不同。emitclosure只是循环变量的闭包,因此它们的范围是安全的。

于 2013-07-18T10:54:26.777 回答