微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript-Promise.all的解析时间比预期的要早

我正在使用Promises编写第一段代码,并且得到了一些意想不到的结果.我有一些看起来像这样的代码(使用jQuery):

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

为了防止该代码运行时页面被阻塞,我尝试使用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();
});

我要实现的目标是,一旦解决了Promise中的Promises,就实例化了Promise2中的Promises.解决这些问题后,将隐藏加载微调器.

我得到的效果是,尽管页面没有被长时间阻塞,但所有的Promise都设置好之后,微调框就会消失,而不是等它们解决之后再消失.

我可以看到,promises2 Promises不会解决,直到promises中的所有事情都解决了,所以我不明白为什么会这样.我想这可能是由于我不能正确理解Promise,或者是低估了使代码异步.

解决方法:

在填充promise2之前,您要在Promise.all上调用Promise.all,实际上,当您调用它时,它包含一个空数组,因此它在一个空数组上调用Promise.all,因此它可以立即解决而无需等待promises中的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次超时:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐