jQuery deferred behaviour in for loop

瘦欲@ 提交于 2019-12-05 02:47:16

问题


I recently asked a question about the behaviour of jquery deferred in a for loop. Link here

I received a working answer but I don't understand why it works.

If I have the following code:

function update(callbacks) {
    return $.Deferred(function(dfr) {
        setTimeout(function() {
            callbacks.success()
        }, 1000);
        dfr.resolve();
    }).promise();
}

function updateElements(deferreds) {
    for (var i = 0; i < 5; i++) {
        (function() {
            var index = i;
            deferreds.push(update({
                success: function() {
                    alert(index);
                }
            }));
        })();
    }
};

(function() {
    var deffereds = [];
    updateElements(deffereds);
    $.when.apply($, deffereds).then(function() {}, function() {});
})();​

It returns 5 alert windows with the values 0 through to 4. If I change the updateElements method to:

function updateElements(deferreds) {
    for (var i = 0; i < 5; i++) {
        var index = i;
        deferreds.push(update({
            success: function() {
                alert(index);
            }
        }));
    }
};

It returns 5 alert windows with the value 4 only. Could someone please explain this behaviour? I'm struggling to understand where the difference comes about.

Thanks!


回答1:


The reason that it does that is because you have closed over a loop with

(function() {
        var index = i;
        deferreds.push(update({
            success: function() {
                alert(index);
            }
        }));
})();

This self executing block turns into a static value because it has no external values passed in. As in the answer you linked, you need to pass that value in. Note the key difference where the value is given at the end of the IEFE (immediately executed function expression). Sorry for the caps, but this needs emphasis.

(function(VALUE_ACCEPTED){
  //VALUE_ACCEPTED accepts the passed value of VALUE_PASSED
})(VALUE_PASSED)

So that your code becomes this:

function updateElements(deferreds) {
for (var i = 0; i < 5; i++) {
    (function(valueAccepted) { // valueAccepted = the passed in value from i
        var index = valueAccepted;
        deferreds.push(update({
            success: function() {
                alert(index);
            }
        }));
    })(i); // pass in i to valueAccepted
 }
};


来源:https://stackoverflow.com/questions/13394043/jquery-deferred-behaviour-in-for-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!