并行执行的事件发射器与承诺?

Event Emitters vs Promises for parallel execution?

我正在制作大量模块,每个模块都需要 运行 在各个阶段进行编码。我可以为每个阶段使用 Promise.all,例如:

const phase1promise = Promise.all([module1.phase1(),module2.phase1()]);
phase1promise.then(// do next phases)

或者,我可以使用子模块侦听的 "master" 模块中的事件发射器,以便了解何时对阶段进行 运行 代码。反过来,主模块会监听那些子模块的事件发射器,以了解它们何时完成该阶段。我装配了这个事件发射器系统并且它正在工作,但我开始认为 promises 可能会更好,特别是关于并行代码 运行ning。此外,也许 promises 可以被认为是一种更标准的模式。想法?

对不止一次发生的事情使用事件 - 对于顺序数据,使用更专业的事件发射器类型:Streams。

对只发生一次的事情使用承诺。

Promises 是一种请求-响应设计模式。你基本上:

doSomething.then(processResponse);

有了 async/await,promises 已成为执行各种类型的请求-响应的非常强大的工具:并行、系列、批处理等:

// Parallel
results = await Promise.all(a,b,c);

// Serial
for (i=0; i<tasks.length; i++) {
    results.push(await tasks[i]());
}

// Batch 10 tasks in parallel
for (i=0; i<tasks.length; i += 10) {
    currentTasks = tasks.splice(0,10);
    results.push.apply(results, await Promise.all(currentTasks.map(t => t())))
}

但是,Promises 并非旨在拦截多个事件。一旦承诺已解决,其状态将更改为已解决。

这是通用事件发射器的用武之地。对于诸如 onclick 侦听器、等待网络请求(请参阅 Express.js)、等待键盘输入之类的事情 - 不能使用承诺(当然除非你打算在处理一个事件后停止收听更多事件)。

对于某些数据使用承诺的固有请求。

但请注意,这两者都只是关于如何管理异步进程的设计模式。不要使函数异步。还要注意,异步进程可能是也可能不是多线程的。对于网络 I/O 它们是单线程的 - javascript 基本上是并行的 wait,而不是指令的并行执行。但是,有些模块允许您启动新线程或进程(浏览器中的网络工作者和 node.js 中的 child_process)


工作线程

如果您查看网络工作者,您会发现 API 是基于事件的。这是应该的,因为工作人员无法知道主进程将要求它完成的时间和数量。但是你可以轻松地将你自己的主进程 API 包装在一个承诺中,因为它基本上是在做一个请求 - 响应(当然前提是每个请求只会触发工作人员发回 one 回复).

所以有时两者都可以 - 使用有意义的设计模式。

如果每个模块只有一个 "start" 事件和一个 "end" 事件,并且有一位大师协调所有这些,那么承诺将(到目前为止!)更简单。

如果模块应该向 master 注册自己 and/or 为不同的部分发出多个事件,您将拥有更大的灵活性(并且耦合度更低),但是一个更复杂的系统不太清楚理解 - 需要查看 所有 文件来找出依赖关系图。