问题描述
我正在使用Promises编写我的第一段代码,并且得到了一些意想不到的结果。我有一些看起来像这样的代码(使用jQuery):
I'm writing my first piece of code using Promises and am getting some unexpected results. I had some code that looked like this (using jQuery):
$('.loading-spinner').show();
$('.elements').replaceWith(function() {
// Blocking code to generate and return a replacement element
});
$('.newElements').blockingFunction();
$('.loading-spinner').hide();
为防止页面在运行此代码时被阻止,我尝试使用setTimeout和Promises来制作它asyncronous,像这样:
To prevent the page getting blocked when this code it run, I tried using setTimeout and Promises to make it asyncronous, like this:
$('.loading-spinner').show();
var promises = [];
var promises2 = [];
$('.elements').each(function(i, el){
promises[i] = new Promise(function(resolve, reject) {
setTimeout(function() {
$(el).replaceWith(function() {
// Code to generate and return a replacement element
});
resolve(true);
}, 100);
});
});
Promise.all(promises).then(function(values) {
$('.newElements').each(function(i, el) {
promises2[i] = new Promise(function(resolve, reject) {
setTimeout(function() {
$(el).blockingFunction();
resolve(true);
}, 100);
});
});
});
Promise.all(promises2).then(function(values) {
$('.loading-spinner').hide();
});
我想要实现的是,一旦中的承诺承诺,实例化
promises2
中的Promises。一旦解决了这些问题,加载微调器就会被隐藏。
What I'm trying to achieve is that once the Promises in promises
are resolved, the Promises in promises2
are instantiated. Once these are resolved, the loading spinner is hidden.
我得到的效果是,虽然页面没有被阻塞很长时间,但微调器消失了所有的承诺都建立起来,而不是等到它们得到解决。
The effect I'm getting is that, while the page isn't blocked for as long, The spinner disappears as soon as the all the Promises are set up, not waiting until they're resolved.
我可以看到 promises2
Promise不会解决,直到中的所有内容都承诺
已解决,所以我不明白为什么会这样。我想这可能是因为我没有正确理解Promise,或者没有低估使代码异步。
I can see that the the promises2
Promises dont resolve until everything in promises
is resolved, so I dont understand why this is happening. I guess this is down to either me not understanding Promises properly, or not understating making code asynchronous.
推荐答案
你正在呼叫 Promise.all on promises2
,实际上当你调用它时它包含一个空数组,所以它调用 Promise.all
在一个空数组上,因此它立即解析而无需等待 promises
中的承诺。
You're calling Promise.all
on promises2
before you populate it, in fact when you call it it contains an empty array so it calls Promise.all
on an empty array and thus it resolves immediately without waiting for the promises in promises
.
快速修复:
function delay(ms){ // quick promisified delay function
return new Promise(function(r){ setTimeout(r,ms);});
}
var promises = $('.elements').map(function(i, el){
return delay(100).then(function(){
$(el).replaceWith(function() {
// Code to generate and return a replacement element
});
});
Promises.all(promises).then(function(els){
var ps = $('.newElements').map(function(i, el) {
return delay(100).then(function(){
$(el).blockingFunction();
});
});
return Promise.all(ps);
}).then(function(){
$('.loading-spinner').hide();
});
我们可以做得更好,但是没有理由为 n
元素触发 n
超时:
We can do better though, there is no reason to fire n
timeouts for n
elements:
delay(100).then(function(){
$(".elements").each(function(i,el){
$(el).replaceWith(function(){ /* code to generate element */});
});
}).
then(function(){ return delay(100); }).
then(function(){
$('.newElements').each(function(i, el) { $(el).blockingFunction(); });
}).then(function(){
$('.loading-spinner').hide();
}).catch(function(err){
throw err;
});
这篇关于Promise.all比预期更早解决的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!