Promise.all似乎立即解决了

时间:2014-12-11 18:05:46

标签: javascript jquery promise

我发布了similar question related to Ember.RSVP.all,但我发现其行为与Promise.all行为相同。如果我违反任何规则,请通过单独提交来告诉我。

我正在尝试在承诺链中使用Promise.all。我的例子比我的使用简单得多,但它证明了这个问题。在一系列承诺的中间,我有一套承诺,在链条可以继续之前都需要解决 - 正是我所理解的Promise.all是为了。

不幸的是,当我返回Promise.all对象时,链中的下一个promise立即运行,而不等待传递给all()的promise。

我已经设置了一个js小提琴,用我能想到的最佳方式进行演示:

请注意,First和Second都在几乎完全相同的时间解决,当Second应该在1s promise之后。第三和第四按预期进行。

http://jsfiddle.net/vqut9zy2/

小提琴代码如下所示:

function delayAjax(delay) {
    return $.ajax({
        url: '/echo/json/',
        data: {
            json: '',
            delay: delay,
        }
    });
}

delayAjax(1).then(function() {
    $('#first').addClass('red');
    var proms = [delayAjax(1), delayAjax(1)];
    return Promise.all(proms).then(function() {
        $('#onepointfive').addClass('red');
    });
}).then(function() {
    $('#second').addClass('red');
    return delayAjax(1);
}).then(function() {
    $('#third').addClass('red');
    return delayAjax(1);
}).then(function() {
    $('#fourth').addClass('red');
});

HTML

<div id="first">First</div>
<div id="onepointfive">One point five</div>
<div id="second">Second</div>
<div id="third">Third</div>
<div id="fourth">Fourth</div>

2 个答案:

答案 0 :(得分:2)

你需要先将jQuery延迟转换为承诺。

function delayAjax(delay) {
    return Promise.resolve($.ajax({
        url: '/echo/json/',
        data: {
            json: '',
            delay: delay,
        }
    }));
}

http://jsfiddle.net/evilbuck/vqut9zy2/3/

答案 1 :(得分:0)

You Don't Know JS: Async & Performance中有一节讨论如何管理不可信赖的问题:Trustable Promise?

确实以Promise.resolve(thenable)作为解决此问题的方法。

我不太了解您为什么会目睹您的行为,但Domenic Denicola的文章You're Missing the Point of Promises介绍了为什么jQuery的延迟不是真正的承诺,以及为什么它们有问题。在文章的最后,他提供了处理Q库中不可信任的承诺的方法,即使用Q.when()(Angularjs $q服务也为此提供.when()方法目的):

return Q.when($.ajax({
    url: '/echo/json/',
    data: {
        json: '',
        delay: delay,
    }
}));