【问题标题】:Side effects when async operating on arrays对数组进行异步操作时的副作用
【发布时间】:2016-08-25 22:33:17
【问题描述】:

我正在学习 node.js atm,现在我在问自己:

普通数组有多“线程安全”?

例子:

var myArr = ["Alpha", "Beta", "Gamma", "Delta"];

ee.on('event', function(itemString) {
    //Loop over an Array that could change its length while looping through
    for(var i=0; i<myArr.length; i++) {
        // delete the item out of the array
        if(myArr[i] == itemString)
            myArr.splice(i,1);
    }
});

如果在 ee-Object 上触发了多个事件,是否有可能因为索引已经被拼接掉而导致 for 循环失败?

或者说不同:有一种方法可以确保循环不会因为任何元素可能被同一事件的另一个回调调用删除而跳过或失败?

谢谢 :)

【问题讨论】:

  • Node.js 是单线程的,因此您的代码不会被另一个线程中断。但是上面的代码被破坏了,你在迭代期间修改数组的方式会导致有时跳过元素。
  • 我认为代码是正确的,假设数组的所有元素都不同。 (你可以跳过一个元素,但只有在你找到一个匹配的元素之后,这意味着没有更多的匹配元素,所以你不在乎。)

标签: javascript node.js


【解决方案1】:

node.js 是单线程的,它不会中断同步执行。

不过,您正在修改数组,同时按其长度对其进行迭代,这可能会导致跳过元素。 此外,您的事件不准备为同一个数组元素触发两次。

【讨论】:

  • 定义“爆炸?”我很确定最坏的情况是元素被跳过。
  • @smarx 好吧,如果你有 10 个元素,在第 9 次迭代中删除一个,那么将找不到第 10 个元素
  • 如果数组变短,for 循环将永远不会到达第 10 个元素。 (条件i &lt; myArr.length 将在i 达到值9 之前失败。)
【解决方案2】:

我认为我们已经很好地解决了线程问题,但您仍然应该解决循环问题。有关我正在谈论的“跳过”问题的示例,请尝试以下操作:

var a = [1, 2, 3, 4, 5];
for (var i = 0; i < a.length; i++) {
    console.log(a[i]);
    if (a[i] === 2) {
        a.splice(i, 1);
    }
}

输出:

1
2
4
5

请注意,这个循环甚至从未见过数字 3。

修复这种循环的一种常见方法是向后移动,以便您可以在迭代数组时安全地删除数组元素:

var a = [1, 2, 3, 4, 5];
for (var i = a.length - 1; i >= 0; i--) {
    console.log(a[i]);
    if (a[i] === 2) {
        a.splice(i, 1);
    }
}

输出:

5
4
3
2
1

请注意,我们以这种方式查看数组的所有元素。

【讨论】:

  • 我想知道的是是否有办法确保循环不会跳过或失败,因为任何元素可能会被同一事​​件的另一个回调调用删除。
  • 关于您的回答:我还没有注意到这种行为。. 向后循环数组与以“正常”方式循环有什么区别?
  • 正如我所说,Node.js 是单线程的,所以没有其他线程可以打断你。至于为什么向后迭代会解决跳过问题,我建议您手动单步执行,注意i 的值和数组的内容。
猜你喜欢
  • 1970-01-01
  • 2020-01-17
  • 2014-12-20
  • 2018-01-20
  • 1970-01-01
  • 2016-12-20
  • 2023-03-16
  • 2016-12-08
  • 2019-05-18
相关资源
最近更新 更多