javascript 使用 EventEmitter 编写异步函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17740988/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 09:26:28  来源:igfitidea点击:

write async function with EventEmitter

javascriptnode.jsasynchronous

提问by zero_coding

I am new in node and try to use async and event behavior advantages in node. I used to understand from node, everything that handle with Event object, it gonna be async execution.
Then i had try this, consider following code:

我是节点的新手,并尝试在节点中使用异步和事件行为优势。我曾经从 node 中了解到,所有处理 Event 对象的事情都是异步执行的。
然后我尝试了这个,考虑以下代码:

var events = require("events");

var event = new events.EventEmitter();


event.on("work", function () {

    for (var i = 0; i <= 10; i++) {
        console.log("I do my work " + i);
    }

    event.emit("done");
});

var async = function (cb) {

    event.on("done", cb);
    event.emit("work");
    for (var i = 0; i <= 10; i++) {
        console.log("Async " + i);
    }
}


async(function () {
    console.log("I am done callback!");
});  

This is async execution? In my opinion no! Why, because i had read this sentence many:

这是异步执行?在我看来没有!为什么,因为这句话我读过很多:

An event is fired, so go and do something and then when you have finished it, come back and tell me, but in meanwhile i will do something else.

一个事件被触发,所以去做一些事情,然后当你完成它时,回来告诉我,但与此同时我会做其他事情。

Like a fast food restaurant scenario. But the code above, when the event work gonna fired, following sequence will happen:

就像快餐店的场景。但是上面的代码,当事件工作被触发时,会发生以下序列:

  1. go into the callback
  2. let through the loop
  3. output I do my work n
  4. fired the done event
  5. output I am done callback!
  6. output Async n
  1. 进入回调
  2. 让通过循环
  3. 输出我做我的工作 n
  4. 触发 done 事件
  5. 输出我完成回调!
  6. 输出异步n

why I am done callback! gonna output before Async n? Why is here not like fast food restaurant scenario, like

为什么我完成回调!会在 Async n 之前输出吗?为什么这里不像快餐店的场景,像

the work event is fired, go and do you stuff and come back when you done, in meanwhile i will output Async n

工作事件被触发,去做你的事情并在你完成后回来,同时我将输出 Async n

This is i used to understand about event driven behavior and async in node. But now i am very confused. I know, javascript works on single thread. How can i write an async function with event emitter? But i think is not possible, because when i emit an event, it will immediately execute the handler.

这是我用来了解节点中的事件驱动行为和异步的。但现在我很困惑。我知道,javascript 在单线程上工作。如何使用事件发射器编写异步函数?但我认为这是不可能的,因为当我发出一个事件时,它会立即执行处理程序。

回答by Gabriel Llamas

I used to understand from node, everything that handle with Event object, it gonna be async execution.

我曾经从 node 中了解到,所有处理 Event 对象的事情都是异步执行的。

This is incorrect. Events are synchronous. When you add a listener, you're just saving the callback in an object:

这是不正确的。事件是同步的。添加侦听器时,您只是将回调保存在对象中:

this._events[type].push(listener);

When you emit an event, you're just iterating an array and calling each listener:

当您发出事件时,您只是在迭代一个数组并调用每个侦听器:

for (i = 0; i < len; i++)
      listeners[i].apply(this, args);

Source code: https://github.com/joyent/node/blob/master/lib/events.js

源代码:https: //github.com/joyent/node/blob/master/lib/events.js

This is async execution? In my opinion no!

这是异步执行?在我看来没有!

You are correct. It's async if you call any I/O function or use setImmediate, nextTickor a timer—otherwise, it's synchronous. A synchronous code being written asynchrously doesn't convert it to an asynchrous code.

你是对的。它的异步,如果你调用任何I / O功能或使用setImmediatenextTick或定时器,否则,它是同步的。异步编写的同步代码不会将其转换为异步代码。

why I am done callback! gonna output before Async n?

为什么我完成回调!会在 Async n 之前输出吗?

Because when you receive the "done" callback you call to "cb":

因为当您收到“done”回调时,您会调用“cb”:

event.on("done", cb);

When cbreturns, the "Async n" loop is executed.

cb返回时,“异步N”循环执行。

How can i write an async function with event emitter?

如何使用事件发射器编写异步函数?

Using setImmediateor process.nextTick.

使用setImmediateprocess.nextTick

If you want to postpone the "I do my work" loop execution, you can wrap the line events.emit ("work")with nextTick.

如果你想推迟“我做我的工作”循环执行,你可以events.emit ("work")nextTick.

var events = require("events");

var event = new events.EventEmitter();


event.on("work", function () {

    for (var i = 0; i <= 10; i++) {
        console.log("I do my work " + i);
    }

    event.emit("done");
});

var async = function (cb) {

    event.on("done", cb);
    process.nextTick (function () {         //<-----
        event.emit("work");
    });                                     //<-----
    for (var i = 0; i <= 10; i++) {
        console.log("Async " + i);
    }
}


async(function () {
    console.log("I am done callback!");
});  

This will print:

这将打印:

Async 0
Async 1
Async 2
Async 3
Async 4
Async 5
Async 6
Async 7
Async 8
Async 9
Async 10
I do my work 0
I do my work 1
I do my work 2
I do my work 3
I do my work 4
I do my work 5
I do my work 6
I do my work 7
I do my work 8
I do my work 9
I do my work 10
I am done callback!