0

我正在调用一个函数,它将编辑内容保存到数据库并返回一个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都是ArrayObject。我的猜测是,因为Array' 的存储引用,每次循环都会覆盖引用。Array在将它们传递给 之前,我尝试创建 's 的深层副本layer.applyEdits,但这没有效果。

4

1 回答 1

0

每次循环都会覆盖引用

确切地。不是因为它们是对数组的引用,而是因为它们是被覆盖的变量中的值。检查循环内的 JavaScript 闭包——简单实用的示例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将它们直接传递给回调函数(或将 Dojolang.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)));
于 2013-07-22T20:49:48.733 回答