首先,我是一个蟒蛇,而不是一个javascripter - 请善待。
在热门的MVVM Javascript framework from a popular Internet search provider中,有一个名为Scope的类。
此类有一个名为$watch
的方法,用于注册每次触发Scope.$digest
时应调用的回调(称为侦听器)。对Scope.$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)
...
由于可以从另一个侦听器注册或销毁侦听器there are two race conditions here:
length = watchers.length
和watch = watchers[length]
之间取消注册某个侦听器时,watch
将被取消定义,对watch.get(current)
的调用将失败(undefined没有方法获取)。我想对watch
的存在进行简单检查可以解决条件#1:
if (watch && (value = watch.get(current)) !== (last = watch.last)
我不确定如何解决条件#2。迭代时不应修改数组 - 我的第一个想法是:为什么while (length--)
?然后我在源评论中读到:
- 使用while(count--){...}
优化循环操作
- 这意味着为了保持与添加相同的执行顺序 我们必须在开头(shift)而不是at处向数组添加项目 结束(推)
在Python中,我可能会尝试使用队列来解决它。两个问题:
[编辑]
Samuel Neff评论说,由于JavaScript不是多线程的,因此这不是真正的竞争条件。
一个更客观的问题是:考虑到性能和内存占用,我该怎么做才能防止回调导致的错误,这些错误修改了我在使用{{{i}时迭代的数组1}}模式循环回调数组?
答案 0 :(得分:3)
JavaScript不是多线程的。您不必担心在连续的代码行之间修改对象的另一个“线程”。
如果依赖于以特定顺序回调的回调,则可能存在竞争条件,但您不必担心普通多线程语言中的竞争条件。
答案 1 :(得分:1)
我过去几次解决这类问题的方式(例如,在服务器代码中迭代连接时)是通过向临时数组添加新的侦听器(或者在我的情况下,连接)/#34 ;队列"
在我的主循环中,我将首先浏览现有连接,删除已标记为已删除的连接并调度其他线程以处理需要服务的连接。其他线程可以注册到队列数组的连接或标记从主数组中删除的连接,但实际上不会删除它们。这照顾了你的第一次竞争条件。
通过让我的主循环将队列数组原子地链接到主数组的末尾来解决第二种竞争条件,从而启动空队列数组并通过队列数组的先前内容扩展主数组。然后主循环完成了主数组的新扩展内容。