在while循环内承诺

时间:2020-01-29 20:50:32

标签: loops while-loop promise es6-promise

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

我有这段代码,因此只有在解决了先前的承诺后,才应运行每个承诺。因此,当我开始执行此任务时,我写了这样的内容:

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

请注意,我的prepare函数返回一个promise,该承诺在加载图像并执行某些其他逻辑后得到解决。但是我注意到我的代码只在等待第一个承诺得到解决,然后立即下载所有下一个图像。

我更改了代码,编写了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时会创建链接使用包装函数,因为它保留了其值,并且在知道由于循环而发生更改时避免了链接,但我不太确定。

有人可以帮我理解吗?

1 个答案:

答案 0 :(得分:1)

在第一个代码行中:

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

太早拨打prepare(i).then()希望您传递一个函数引用,.then()基础结构可以在以后某个时间调用它。但是,按照上面的结构方式,您正在立即调用prepare(i)并将该返回值传递给.then()。那不是你想要的。

您的第二个版本:

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

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

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

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

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