我想知道我在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时会创建链接使用包装函数,因为它保留了其值,并且在知道由于循环而发生更改时避免了链接,但我不太确定。
有人可以帮我理解吗?
答案 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
的值会在正确的时间获取,并保存在绑定函数中供以后使用。