Javascript: функция в setTimeout и ссылки - PullRequest
2 голосов
/ 11 января 2012

У меня проблема с вызовом функции в setTimeout в цикле.
Параметры, передаваемые в функцию, являются последними значениями, вычисленными в цикле для каждой итерации, см. Пример ниже.

for(var i=0; i<datesYM.length; ++i) {
    console.log(datesYM[i]);
    var dateYM = datesYM[i];
    setTimeout(function() {
        myDB.markMonthsValuesAsUpdated2(myDoctorId, dateYM)
    }, Math.floor(Math.random()*5001));
}

myDB.markMonthsValuesAsUpdated2 = function(myDoctorId, dateYM) {
    console.log(dateYM);
    [...]

Печать:

2012-01
2012-02
2012-03
2012-04
2012-05
2012-06
2012-07

2012-07
2012-07
2012-07
2012-07
2012-07
2012-07
2012-07

Ответы [ 2 ]

5 голосов
/ 11 января 2012

Обертка тела в его собственную самовыполняющуюся функцию для принудительного создания новой области:

for(var i=0; i<datesYM.length; ++i) {
    console.log(datesYM[i]);
    var dateYM = datesYM[i];
    (function(dateYM) {
        setTimeout(function() {
            myDB.markMonthsValuesAsUpdated2(myDoctorId, dateYM)
        }, Math.floor(Math.random()*5001));
    })(dateYM);
}

Без этого каждая функция, созданная в цикле, закрывается над тем же экземпляром из dateYM, который имеет значение последней итерации ко времени выполнения любой из этих функций.Поскольку JavaScript имеет область действия функции, функция-оболочка создает новый dateYM на каждой итерации, поэтому каждая новая функция, переданная в setTimeout, имеет свой собственный экземпляр.

1 голос
/ 11 января 2012

Создание области видимости переменной с помощью функции, которая создает и возвращает обработчик тайм-аута.

function create_timeout_handler(myDoctorId, dateYM) {
    return function() {
        myDB.markMonthsValuesAsUpdated2(myDoctorId, dateYM)
    };
}

Затем вызовите эту функцию и передайте ей все, что нужно для определения области действия.

setTimeout( create_timeout_handler(myDoctorId, dateYM), Math.floor(Math.random()*5001));

Это потому, что каждая функция, которую вы давали setTimeout, создавалась в одной и той же области видимости переменной, поэтому все они ссылались на одну и ту же переменную dateYM, которая перезаписывалась в цикле.

Передача dateYM другой функции, которая создает и возвращает обработчик, гарантирует, что каждый обработчик ссылается на переменную dateYM, уникальную для каждого вызова create_timeout_handler.

...