就效率和优雅而言,添加和删除事件侦听器还是使用 global/high-level 变量来控制发射器事件逻辑更好?

In terms of efficiency and elegance, is it better to add and remove event listeners or use global/high-level variables to control emitter event logic?

为了澄清我的问题,这里有两个 Javascript-esque 伪代码示例。 以下是相同的示例,但使用了更多代码来对它们进行上下文化:http://pastebin.com/fRjW5qp6

看看我是如何使用条件语句来防止套接字在已经触发一次之后触发重要的事件逻辑(例如,我在事件侦听器被触发后将 socket.loginBuilt 设置为 true)。

socket.on('login screen built', socketLoginScreenBuilt);

  function socketLoginScreenBuilt() {
    // See how I'm using this conditional to prevent sockets from triggering the important event logic after they've already triggered it once (since I set socket.loginBuilt to true in the logic)
    if (!socket.loginBuilt) {
      numberOfSocketsWithBuiltLoginScreens++;
      socket.loginBuilt = true;

      if (numberOfSocketsWithBuiltLoginScreens === io.sockets.sockets.length) {
        app.emit('all login screens built')
      }
    }
  }

  socket.on('login credentials', socketLoginCredentials);
  
  function socketLoginCredentials(credentials) {
    if (readyForLoginCredentials) {
      socket.username = credentials.username;
      socket.password = credentials.password;
      
      socket.emit('user stored data', socket.userData);
    }
  }
});

-------------------- 或 --------------------

请注意我没有使用上面使用的条件,因为我第一次删除了函数 运行 之后的侦听器。这样我就可以确定套接字不会多次触发重要的事件逻辑。

socket.on('login screen built', socketLoginScreenBuilt);  

function socketLoginScreenBuilt() {
  // Notice how I'm not using a conditional here because I remove the 'login screen built' listener after this function is first ran. In that way I'll be certain that a socket won't trigger the important event logic multiple times
  numberOfSocketsWithBuiltLoginScreens++;
  socket.loginBuilt = true;

  if (numberOfSocketsWithBuiltLoginScreens === io.sockets.sockets.length) {
    app.emit('all login screens built')
  }
  
  socket.removeListener('login screen built', socketLoginScreenBuilt);
}

socket.on('login credentials', socketLoginCredentials);

function socketLoginCredentials(credentials) {

  socket.username = credentials.username;
  socket.password = credentials.password;

  socket.emit('user stored data', socket.userData);
  socket.removeListener('login credentials', socketLoginCredentials);
}

我想澄清两件事:

  • Node.js 是 event-driven。
  • 全局变量是 evil(有一个 C/C++ 标签,但它们很重要)

因此,为了保持您的代码整洁,up-to-standards,您应该使用 event-driven 方法而不是全局变量。

顺便说一句,在这两种情况下,您 都使用 全局变量 numberOfSocketsWithBuiltLoginScreens.