while 循环中的承诺

Promises within while loop

我想知道我在 while 循环中得到一些承诺的行为的原因。

我有这段代码,所以它应该 运行 每个承诺只有在前一个承诺被解决之后。所以当我开始这个任务时,我写了这样的东西:

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

请注意,我的准备函数 returns 是在加载图像并执行其他一些逻辑时解析的承诺。但我注意到我的代码只是在等待第一个承诺被解决,然后所有下一个图像都立即下载。

我更改了我的代码并编写了 prepareImage 函数来分离逻辑,因此我收到了要下载的索引并且我在 while 循环中具有相同的逻辑。

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 创建了链接当我使用包装函数时,因为它保留了它的值,并且当它知道它由于循环而改变时避免了链接,但我不太确定。

谁能帮我理解一下?

在第一个这行代码中:

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

打电话给 prepare(i) 太早了。 .then() 希望您向它传递一个函数引用,.then() 基础架构稍后可以调用该函数引用。但是,按照上面的结构,您将立即调用 prepare(i) 并将该 return 值传递给 .then()。这不是你想要的。

你的第二个版本:

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

正在正确传递函数引用,因此 prepare(i) 稍后可以由 promise 基础结构调用。我注意到您还使用包装函数对第二个函数进行了单独更改,以正确封装值 if i ,因此在调用 prepare(i) 之前它没有更改。这也是使这个版本工作所必需的。

仅供参考,您也可以使用 .bind() 作为快捷方式:

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

这将创建一个临时函数,稍后调用时将调用 prepare(i)。这样做不需要包装函数,因为 i 的值是在正确的时间抓取并保存在绑定函数中供以后使用的。