Promise.all比预期更早解决 [英] Promise.all resolving earlier than expected

查看:66
本文介绍了Promise.all比预期更早解决的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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();
});

我想要实现的是,一旦中的承诺承诺<解析/ code>,实例化 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.

推荐答案

你正在呼叫<你填充它之前code> 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比预期更早解决的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆