简体   繁体   English

Promise.All解决方案早于预期

[英]Promise.all resolving earlier than expected

I'm writing my first piece of code using Promises and am getting some unexpected results. 我正在使用Promises编写第一段代码,并且得到了一些意想不到的结果。 I had some code that looked like this (using jQuery): 我有一些看起来像这样的代码(使用jQuery):

$('.loading-spinner').show();
$('.elements').replaceWith(function() {
   // Blocking code to generate and return a replacement element
});
$('.newElements').blockingFunction();
$('.loading-spinner').hide();

To prevent the page getting blocked when this code it run, I tried using setTimeout and Promises to make it asyncronous, like this: 为了防止该代码运行时页面被阻塞,我尝试使用setTimeout和Promises使其异步,如下所示:

$('.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();
});

What I'm trying to achieve is that once the Promises in promises are resolved, the Promises in promises2 are instantiated. 我正在努力实现的是,一旦在承诺promises得到解决,在承诺promises2被实例化。 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. 我得到的效果是,尽管页面没有被长时间阻塞,但所有的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. 我可以看到, promises2 Promises不会解决,直到promises所有事情都解决了,所以我不明白为什么会这样。 I guess this is down to either me not understanding Promises properly, or not understating making code asynchronous. 我想这可能是由于我不能正确理解Promise,或者是低估了使代码异步。

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 . 你打电话Promise.allpromises2你填充它之前,其实当你调用它,它包含一个空的阵列,它调用Promise.all空阵列上,从而立即解决,而无需等待中的承诺promises


Quick fix: 快速解决:

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();
});

We can do better though, there is no reason to fire n timeouts for n elements: 不过,我们可以做得更好,没有理由为n元素触发n超时:

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;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM