首先,我是 pythonist,而不是 javascripter - 请善待。
在流行的 Internet 搜索提供商的流行MVVM Javascript框架中,有一个名为 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)
...
由于可以从另一个侦听器注册或销毁侦听器,因此这里有两个竞争条件:
- 当侦听器在
length = watchers.length
and之间注销时watch = watchers[length]
,watch
将是未定义的并且对的调用watch.get(current)
将失败(未定义没有方法 get)。 - 当一个监听器被另一个监听器注册时,它可能会被跳过。
我想一个简单的检查是否存在watch
将修复条件#1:
if (watch && (value = watch.get(current)) !== (last = watch.last)
我不确定如何解决条件 #2。迭代时不应修改数组 - 我的第一个想法是:为什么while (length--)
?然后我阅读了源评论:
- 通过使用 while(count--) { ... } 优化循环操作
- 这意味着为了保持与加法相同的执行顺序,我们必须在数组的开头(移位)而不是结尾(推)添加项目
在 Python 中,我可能会尝试使用队列来解决它。两个问题:
- 当目标是最大化性能和节省内存时,在 javascript 中处理这个问题的惯用方法是什么?
- 我应该如何进行竞争条件的单元测试(或者我应该使用端到端测试)?
[编辑]
Samuel Neff 评论说,由于 JavaScript 不是多线程的,这并不是真正的竞争条件。
一个更客观的问题是:考虑到性能和内存占用,我可以做些什么来防止在使用模式循环遍历回调数组时修改我正在迭代while (length--)
的数组的回调引起的错误?