1

假设我有一个站点,它通过对服务的 HTTP 调用保存电话号码,并且该服务返回电话号码条目的新 id 以绑定到页面上的电话号码。

在这种情况下,电话存储在一个名为“电话”的数组中,datacontext.telephones.updateData 在 $.Deferred([service call logic]).promise(); 中将电话发送到服务器。

uploadTelephones = function (deffered) {
                for (var i = 0; i < telephones.length; i++){
                        deffered.push(datacontext.telephones.updateData(telephones[i], {
                            success: function (response) {
                                telephones[i].telephoneId = response;                                    
                            },
                            error: function () {
                                logger.error('Stuff errored');
                            }
                        }));                            
                 }
            }

现在,如果我打电话:

function(){
    var deferreds = [];
    uploadTelephones(deferreds);
    $.when.apply($, deferreds)
                    .then(function () {
                        editing(false);
                        complete();
                    },
                    function () {
                        complete();
                    });
}

奇怪的事情发生了。所有电话都被发送回服务并被保存。当调用uploadTelephones方法中的'success'回调,新的id为'response'时,无论查询涉及哪个电话,i的值始终为telephones.length+1和line

telephones[i].telephoneId = response; 

抛出错误,因为电话[i] 不存在。

谁能告诉我如何在成功回调中保留 i 的各个值?

4

1 回答 1

3

您的所有闭包(您的匿名函数在本地范围内捕获变量)都引用相同的索引变量,该变量将具有telephones.lengthafter loop execution 的值。您需要为每次for循环创建一个不同的变量,保存i创建实例的值以供以后使用。

要创建一个新的不同变量,最简单的方法是使用代码创建一个匿名函数,该函数用于捕获循环中特定位置的值并立即执行它。

要么这个:

for (var i = 0; i < telephones.length; i++)
{
    (function () {
        var saved = i;
        deffered.push(datacontext.telephones.updateData(telephones[saved],
        {
            success: function (response)
            {
                telephones[saved].telephoneId = response;
            },
            error: function ()
            {
                logger.error('Stuff errored ');
            }
        }));
    })();
}

或这个:

for (var i = 0; i < telephones.length; i++)
{
    (function (saved) {
        deffered.push(datacontext.telephones.updateData(telephones[saved],
        {
            success: function (response)
            {
                telephones[saved].telephoneId = response;
            },
            error: function ()
            {
                logger.error('Stuff errored ');
            }
        }));
    })(i);
}  

应该管用。

不过,现在这有点难看。由于您已经一遍又一遍地执行匿名函数的过程,如果您希望代码更简洁,您可能需要查看Array.forEach并使用传入的任何参数,或者只使用jQuery.each因为您已经在使用 jQuery。

于 2012-11-13T22:01:28.670 回答