JavaScript Promise 和竞争条件

标签 javascript promise race-condition q

我刚开始使用 Promises在 JavaScript 中使用 Q library .我遇到了竞争条件,想知道解决它的最佳方法是什么。

问题是 Q 总是使用 process.nextTick()(在 Promises/A+ 规范中也提到)调用回调,这意味着我可能会错过当时对象的一些状态变化在 promise 的解决和回调被调用的时间之间。我的具体问题是我有一个传入连接并且丢失了第一条消息。使用 EventEmitter 分发消息。

代码看起来像这样。它使用 palava-client (但问题应该是普遍的)并且是用 CoffeeScript 写的:

defer = q.defer()
session.on 'peer_joined', (peer) ->
  defer.resolve(peer)
return defer.promise

还有别的地方

peer_promise.then (peer) ->
  peer.on 'message', (msg) ->
    console.log "Message received:", msg

第一条消息有时会丢失,因为它们在 promise 收到通知之前就已发出。仅使用 EventEmitter 和回调不会出现此问题,因为总是立即调用回调,阻止 JavaScript 线程处理传入消息。

以下代码绝不会丢失消息:

session.on 'peer_joined', (peer) ->
  peer.on 'message', (msg) ->
    console.log "Message received:", msg

您认为我可以使用 promises 解决问题吗?我真的很想在我的抽象层中继续使用它们,以确保只接受一个对等方。有没有其他方法可以避免这种竞争条件?

最佳答案

作为平时推广使用promise的人,我的建议是:

不要在这里使用 promise

Promises 代表一次性事件。它们是对 的抽象,一个 promise 改变了它的状态,它不能再被改变。一个 promise 以未决状态开始,一次状态变为已完成或已拒绝。

您面临的场景是您有很多用户,每个用户都加入并需要添加事件,用户可能会“离开”,您的场景根本无法描述 promise 所擅长的相同线性流。 Promises 对于特定场景很有用——它们并不适用于所有并发问题。在这里使用事件发射器是非常合适的。

您的情况(用户加入)并不真正代表已解决的代理操作。 “不错过消息”的代码确实更正确

如果你还是选择在这里使用promises

您可以做一些事情:

  • 您可以使用 Q 的进度事件并在创建阶段添加进度处理程序。请注意,Kris(Q 的作者)称进程已被破坏,并将在 Q 的下一版本中将其删除。我建议不要这样做。
  • 您可以将 message 回调包装为仅在附加处理程序后触发 - 累积创建处理程序时触发的项目(在数组中),然后在消息处理程序时触发它们添加(在您解决后,在延迟的 .then 中返回。

关于JavaScript Promise 和竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27081390/

相关文章:

javascript - 无法从 d3 json 文件中读取路径 d 值?

javascript - 谷歌图表中的 Y 轴以 "General 1, General 2"等递增 - Javascript

javascript - javascript promise中的 "then block"和 "then handler"有什么区别?

javascript - IE8 -- JS 的异步验证?

javascript - 在 javascript 或 momentjs 中获取给定的日期格式(指定格式的字符串)

javascript - 提交时跳转到 anchor

javascript - Promise.all 不等待 firestore 查询循环

javascript - TypeScript promise TS2304 TS2529

java - 在进程关闭之前读取所有进程输出

javascript - 有没有办法在 JavaScript/jQuery 中强制 DOM 焦点?