我可以在单个循环中使用 dojo.forEach 删除商店中的对象吗?

Can I remove objects in a store using dojo.forEach in a single loop?

我想遍历商店中的对象并在它们不满足某些条件时将其删除,例如:

this.myStore = new Observable(new Memory({identifier: "id", data: []}));

...

array.forEach(this.myStore.data, lang.hitch(this, function(foo){
    if (foo.status === Status.REMOVE){
        this.myStore.remove(foo.id);
    }
    else{
        this.myStore.get(foo.id).status = Status.NONE;
    }
}));

然而,一旦我在商店中删除了一个对象,foo 对象就会在下一个循环中变为未定义。

这是可行的还是错误的方法?

我发现的解决方法是首先循环查找我要删除的对象的 ID,并将它们存储在一个数组中。然后我再次循环此 id 数组以删除对象,而不是循环存储数据本身。它有效,但我必须循环两次才能做这样的事情吗?

谢谢

简答

改用store.query().forEach(...)

长答案

store.data 是 属性,dojo/store/Memory 在内部使用它来存储和处理商店中的数据。它特定于 Memory 存储实现,通常不应直接对其进行迭代,尤其是在这些情况下,因为 store.remove 将从该数组中拼接元素,并将数组作为其元素进行迭代拼接出来本身有有趣的不良影响:

  • 使用 ES5 的 Array#forEach,您的循环将在每次删除相同或较低索引的项目时跳过一个项目,因为它按顺序通过数组索引进行,而不会怀疑项目正在从其下方拼接出来.
  • 使用 dojo/_base/array.forEach,你会得到项目跳过行为 错误,因为 dojo/_base/array 中的函数首先缓存数组的长度继续前进,不要指望这个数字会改变。

另一方面,store.query()旨在用于您想要迭代商店中的数据的用例。 QueryResults 对象 returns 甚至提供了 forEachmap 函数,无论您是否在支持 ES5 的浏览器中都可以使用 and 无论您的商店是否同步(一旦检索到异步商店的结果,它就会 运行 异步)。但最重要的是,它 returns 在 Memory 的情况下有自己的数组,所以你不必处理从你下面拼接出来的数组元素。

可运行示例:http://jsfiddle.net/eu6aqxbq/