Dojo使用数组覆盖参数延迟链接

时间:2013-07-22 19:42:26

标签: javascript arrays asynchronous dojo

我正在调用一个保存对数据库的编辑并返回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;

addsupdatesdeletes都是Array的{​​{1}}个。我的猜测是因为Object的商店引用,每次循环都会覆盖引用。我尝试创建Array的深层副本,然后将其传递给Array,但这没有效果。

1 个答案:

答案 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)));