如何在javascript中处理竞争条件?

如何在javascript中处理竞争条件?,javascript,angularjs-directive,race-condition,Javascript,Angularjs Directive,Race Condition,首先,我是一个pythonist,不是javascripter——请善待我 在流行的Javascript中,有一个名为Scope的类 该类有一个名为$watch的方法,用于注册每次激发作用域时都应该调用的回调(称为侦听器)。$digest。调用作用域。$watch返回此侦听器的注销函数 侦听器在以下循环中调用: ... do { // "traverse the scopes" loop if ((watchers = current.$$watchers)) { // proces

首先,我是一个pythonist,不是javascripter——请善待我

在流行的Javascript中,有一个名为Scope的类

该类有一个名为
$watch
的方法,用于注册每次激发
作用域时都应该调用的回调(称为侦听器)。$digest
。调用
作用域。$watch
返回此侦听器的注销函数

侦听器在以下循环中调用:

...
do { // "traverse the scopes" loop
  if ((watchers = current.$$watchers)) {
    // process our watches
    length = watchers.length;
    while (length--) {
      try {
        watch = watchers[length];
        // Most common watches are on primitives, in which case we can short
        // circuit it with === operator, only when === fails do we use .equals
          if ((value = watch.get(current)) !== (last = watch.last)
... 
由于可以从另一个侦听器注册或销毁侦听器,因此:

  • 当在
    length=watchers.length
    watch=watchers[length]
    之间注销侦听器时,
    watch
    将被取消定义,对
    watch.get(current)
    的调用将失败(未定义的方法没有get)
  • 当一个侦听器被另一个侦听器注册时,它可能被跳过
  • 我想一个简单的检查
    watch
    是否存在可以修复条件#1:

    我不知道如何解决条件2。不应该在迭代数组时修改它-我的第一个想法是:为什么
    而(length--)
    ?然后我在源评论中读到:

    • 循环操作通过使用while(count--){…}进行优化
      • 这意味着为了保持与加法相同的执行顺序 我们必须在开始时(shift)而不是在开始时向数组中添加项 结束(推)
    在Python中,我可能会尝试使用队列来解决它。两个问题:

  • 当以最大的性能和内存节约为目标时,javascript中处理这个问题的惯用方法是什么
  • 我应该如何进行竞争条件的单元测试(或者应该改用端到端测试)
  • [编辑]

    Samuel Neff评论说,因为JavaScript不是多线程的,所以这不是真正的竞争条件


    一个更客观的问题是:考虑到性能和内存占用,当使用
    while(length--)
    模式在回调数组上循环时,如果回调修改了我正在迭代的数组,我可以做些什么来防止回调引起的错误

    JavaScript不是多线程的。您不必担心另一个“线程”会在连续的代码行之间修改对象


    如果您依赖于按特定顺序回调,则可能存在竞态条件,但您不必像在普通多线程语言中那样担心竞态条件。

    过去我曾多次解决过类似问题(例如,在服务器代码中迭代连接时)是通过向临时数组/“队列”中添加新的侦听器(或者在我的情况下是连接)

    在我的主循环中,我将首先检查现有的连接,删除标记为已删除的连接,并分派其他线程来处理需要维护的连接。其他线程可以注册到队列数组的连接或将连接标记为从主数组中删除,但实际上不会删除它们。这照顾到了你的第一场比赛状态


    通过让我的主循环原子地将队列数组链接到主数组的末尾,从而启动一个空队列数组,并通过队列数组的先前内容扩展主数组,解决了第二个竞争条件。然后,主循环完成了对主数组新扩展内容的遍历。

    它不是另一个线程;对象在循环中被一个回调修改,同时对其进行迭代。@PauloScardine,这很有意义。我不认为这是比赛条件。我真傻,不知道怎么称呼它。“我正在接受减少误导性措辞的建议。@PauloScardine,啊,现在我明白了这个问题。我想我有一个建议,关于跟踪访问的观察者,并持续循环所有观察者,如果未访问,则处理并继续,直到所有观察者访问。在JS中,你需要很多嵌套循环来完成这项工作,但除非你有成千上万的观察者,否则这并不是一个大的性能问题。
    if (watch && (value = watch.get(current)) !== (last = watch.last)