Обещания в течение цикла - PullRequest
0 голосов
/ 29 января 2020

Я хотел бы знать причину поведения, которое я получаю с некоторыми обещаниями через некоторое время. L oop.

У меня был этот код, поэтому он должен запускать каждое обещание только после предыдущего обещания. решено. Поэтому, когда я запустил эту задачу, я написал что-то вроде этого:

while (i <= totalImages) {
   if (previousDeferred === null) {
     previousDeferred = prepare(i);
   }
   else {
     previousDeferred = previousDeferred.then(prepare(i));
   }
   // code to calculate i value
}

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

Я изменил свой код и написал функцию prepareImage, чтобы отделить логи c, поэтому там я получаю индекс для загрузки, и у меня тот же лог c, который у меня был в то время как l oop.

function prepareImage(i) {
    if (previousDeferred === null) {
        previousDeferred = prepare(i);
    }
    else {
        previousDeferred = previousDeferred.then(function(){
            return prepare(i); 
        });
    }
}

while (i <= totalImages) {
    tryToPrepare(paths[i]);
   // code to calculate i value
}

Так что это работает правильно, но я не знаю причину, по которой первый код не работал, а второй работал должным образом, я думаю, что это что-то, связанное со значением i, возможно js создает цепочку, когда я использую функцию-обертку, так как она сохраняет свое значение и избегает цепочка, когда он знает, что это изменилось из-за l oop, но я не совсем уверен.

Может кто-нибудь помочь мне понять это?

1 Ответ

1 голос
/ 29 января 2020

В первой строке кода:

previousDeferred = previousDeferred.then(prepare(i));

вызывает prepare(i) слишком рано. .then() хочет, чтобы вы передали ему ссылку на функцию, которую инфраструктура .then() может вызвать через некоторое время. Но, как у вас это структурировано выше, вы немедленно вызываете prepare(i) и передаете это возвращаемое значение в .then(). Это не то, что вам нужно.

Ваша вторая версия:

previousDeferred = previousDeferred.then(function(){
    return prepare(i); 
});

правильно передает ссылку на функцию, поэтому prepare(i) может быть вызвана позднее инфраструктурой обещаний. Я отмечаю, что вы также внесли отдельное изменение во второе с помощью функции-оболочки, чтобы правильно инкапсулировать значение, если i, поэтому оно не изменилось до вызова prepare(i). Это также было необходимо для работы этой версии.

К вашему сведению, вы также можете использовать .bind() для ярлыка:

previousDeferred = previousDeferred.then(prepare.bind(null, i));

Это создает временную функцию, которая будет вызывать prepare(i), когда это позже называется. Для этого не потребуется функция-обертка, поскольку значение i захватывается в нужное время и сохраняется в связанной функции для последующего использования.

...