【问题标题】:Is Eventemitter code blocking or notEventemitter 代码是否阻塞
【发布时间】:2018-05-11 14:37:48
【问题描述】:

我正在开展一个项目,其中有一个供稿页面,该页面显示所有用户的所有类型的帖子。键入特定列表页面和帖子的详细信息页面。

页数- 1. 饲料 2. 列表(特定类型) 3. Detail(帖子的细节)

所以我有以下 Mongo 收藏 - 1.饲料 2. type1 帖子 3. type2 帖子 4. type3...

现在,当用户发布新帖子时,我将其保存到相应的集合中,让我们说“type1 post”并将成功返回给浏览器。但我也想用相同的数据更新我的“Feed”集合。我不希望在发送响应之前完成它。因为那会增加用户的等待时间。因此我使用了事件。这是我的代码 -

const emitter = new event.EventEmitter();

function savePost(){
    //  Code to save data to Mongo collection

    emitter.emit('addToFeeds', data);
    console.log('emit done');

    return res.json(data);
}

emitter.on('addToFeeds', function(data){
    // code to save data to Feeds collection
    console.log('emitter msg - ', data);
});

现在,当我检查 console.log 输出时,它首先显示“emitter msg -”,然后是“emit done”。这就是为什么我假设emitter.on 代码在 res.json(data); 之前执行;

现在我想知道事件是否阻塞了代码?如果我必须在后台或发送响应后更新提要,正确的方法是什么?将来我还想实现缓存,因此即使添加了帖子,我也必须更新缓存,这也是我想在发送响应后或在后台执行的操作。

【问题讨论】:

    标签: node.js eventemitter


    【解决方案1】:

    是的,事件是同步和阻塞的。它们是通过简单的函数调用实现的。如果您查看 eventEmitter 代码,要将事件发送给所有侦听器,它实际上只是遍历侦听器数组并一个接一个地调用每个侦听器回调。

    现在我想知道事件是否阻塞了代码?

    是的。在doc for .emit() 中,它是这样说的:“按照注册的顺序,同步调用为名为 eventName 的事件注册的每个侦听器,并将提供的参数传递给每个侦听器。”

    并且,在本节Asynchronous vs. Synchronous 的文档中的更多信息是这样写的:

    EventEmitter 按照注册顺序同步调用所有监听器。这对于确保事件的正确排序和避免竞争条件或逻辑错误非常重要。在适当的时候,监听函数可以使用 setImmediate() 或 process.nextTick() 方法切换到异步操作模式:

    如果我必须在后台或发送响应后更新 Feed,正确的方法是什么?

    如果它希望其他侦听器和其他同步代码在其工作之前完成运行,您的 eventListener 可以使用setTimeout()setImmediate()process.nextTick() 实际执行其代码的时间安排。因此,您注册一个普通的侦听器(它将被同步调用),然后在其中,您可以使用setTimeout()setImmediate()process.nextTick() 并将实际工作放入该回调中。这将延迟运行您的代码,直到触发初始事件的当前 Javascript 运行完毕。

    对于纯 Javascript 代码,node.js 中没有实际的“后台处理”。 node.js 是单线程的,所以当你运行一些 Javascript 时,没有其他的 Javascript 可以运行。实际的后台处理必须使用现有的异步操作(使用本地代码在后台运行事物)如网络 I/O 或磁盘 I/O)或通过运行另一个进程来完成工作(其他进程可以是任何类型的代码,包括另一个 node.js 进程)。

    【讨论】:

    • 阅读您的回答后,我了解了 node.js 的 2 个新功能。我很惊讶地知道我们可以很容易地控制我们的代码在下一个事件循环(tick)中执行。这个link 帮助我理解了 setImmediate 和 nextTick 的区别。
    • 请记住,setImmediate()process.nextTick() 允许您更改代码运行的时间,但它在运行时仍处于阻塞状态(例如,在您的代码时不会处理其他系统事件运行)。稍后运行它可以防止它阻塞当前事件的处理,但不会延迟以后事件的运行。
    • 你的意思是如果我使用这些函数我可以跳过当前的事件循环(当前响应是发送的,用户(浏览器)不必等待)但是在下一个事件循环中处理里面的代码setImmediate 或 process.nextTick() 将阻止来自浏览器的下一个请求响应?如果我们使用集群,我们不会陷入这种情况吧?
    【解决方案2】:

    事件是同步的并且会阻塞。这样做是为了您可以按特定顺序绑定事件并按该顺序级联它们。您可以使每个项目异步,如果您在这些事件中发出 HTTP 请求,这将异步发生,但事件本身是同步启动的。

    见:https://nodejs.org/api/events.html#events_emitter_emit_eventname_args

    还有:https://nodejs.org/api/events.html#events_asynchronous_vs_synchronous

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 2020-09-16
      • 2011-04-09
      • 2017-01-25
      • 1970-01-01
      相关资源
      最近更新 更多