我正在调用一个保存对数据库的编辑并返回dojo/Deferred
的函数。我发现我无法一次保存所有记录,因此我将每个调用限制为一次只发送150条记录,并使用for
循环将几个调用链接在一起。
每次运行此代码时,前150条记录都会成功保存,最后一批记录会成功保存。中间的任何批次似乎都被最终批次覆盖。
以下是代码:
applyEdits : function(layer, adds, updates, deletes, editInterval) {
adds = adds || [];
updates = updates || [];
deletes = deletes || [];
var maxFeatures = Math.max(adds.length, updates.length, deletes.length);
var editInterval = editInterval || 155;
var deferred = new Deferred();
deferred.resolve();
for (var i = 0; i < maxFeatures; i+=editInterval) {
var addGroup = adds.slice(i, i+editInterval);
var updateGroup = updates.slice(i, i+editInterval);
var deleteGroup = deletes.slice(i, i+editInterval);
deferred = deferred.then(lang.hitch(this, function() {
return layer.applyEdits(addGroup, updateGroup, deleteGroup).then(function() {
console.log("success");
}, function(error) {
console.log(error);
});
}));
}
return deferred;
adds
,updates
和deletes
都是Array
的{{1}}个。我的猜测是因为Object
的商店引用,每次循环都会覆盖引用。我尝试创建Array
的深层副本,然后将其传递给Array
,但这没有效果。
答案 0 :(得分:0)
每次循环都会覆盖引用
完全。不是因为它们是对数组的引用,只是因为它们是被覆盖的变量中的值。检查JavaScript closure inside loops – simple practical example以获取计数器变量i
被覆盖的示例。当在循环运行之后执行延迟回调(并且它们之所以这样做是因为它们是异步的),变量将仅保留最后分配的值,即在最后一次迭代中。
要解决这个问题,请使用闭包:
for (var i = 0; i < maxFeatures; i+=editInterval) (function() {
var addGroup = adds.slice(i, i+editInterval);
var updateGroup = updates.slice(i, i+editInterval);
var deleteGroup = deletes.slice(i, i+editInterval);
deferred = deferred.then(lang.hitch(this, function() {
return layer.applyEdits(addGroup, updateGroup, deleteGroup).then(function() {
console.log("success");
}, function(error) {
console.log(error);
});
}));
})();
使用闭合值作为闭包函数的参数,从外部传递它们会更优雅。在您的情况下,您甚至可以bind
将它们直接发送到回调函数(或者对于执行相同操作的旧版浏览器使用Dojo&#39; lang.hitch
):
for (var i = 0; i < maxFeatures; i+=editInterval)
deferred = deferred.then(function(addGroup, updateGroup, deleteGroup) {
return layer.applyEdits(addGroup, updateGroup, deleteGroup).then(function() {
console.log("success");
}, function(error) {
console.log(error);
});
}.bind(this, adds.slice(i, i+editInterval), updates.slice(i, i+editInterval), deletes.slice(i, i+editInterval)));