使用Promises进行顺序加载

时间:2015-06-05 06:08:12

标签: javascript promise ecmascript-6 bluebird es6-promise

我有一个异步调用数组,我希望按顺序调用它,这意味着我不想在第一个完成之前调用第二个promise,依此类推。

在下面的示例中,我有一个循环,可以动态创建独特的图像并将它们附加到页面。我希望按顺序添加图像,但由于某些原因,它们不会按照创建它们的确切顺序始终呈现:

var container = document.getElementById("container");
var promise = Promise.resolve();
for(var i = 0; i<100; i++) {
    (function(i) {
        promise = promise.then(function() {
            createPromise(container, i);
        });
    })(i);
}

function createPromise(container, i) {
    return new Promise(function(resolve,  reject) {
        var img = new Image();
        img.onload = function() {
            container.appendChild(img);
            resolve();
        };
        img.onerror = function() {
            reject();
        };
        img.src = "http://placehold.it/100x100?text=Image+" + i + "&v=" + Date.now();
    });
}
img { float: left; margin: 5px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.27/bluebird.min.js"></script>
<div id="container"></div>

我还创建了一个Fiddle来说明问题。

我使用蓝鸟,但我更喜欢坚持本机ES6实现。

1 个答案:

答案 0 :(得分:3)

如果我是正确的,这个块导致了问题:

    promise = promise.then(function() {
        createPromise(container, i);
    });

createPromise返回一个promise但是,在then内你没有返回那个promise,所以它会假设return undefined;(所有js函数的默认值),因此没有后续的promise等待前辈们在开始前完成。尝试将其更改为:

    promise = promise.then(function() {
        return createPromise(container, i);
    });

var container = document.getElementById("container");
var promise = Promise.resolve();
for(var i = 0; i<100; i++) {
    (function(i) {
        promise = promise.then(function() {
            return createPromise(container, i);
        });
    })(i);
}

function createPromise(container, i) {
    return new Promise(function(resolve,  reject) {
        var img = new Image();
        img.onload = function() {
            container.appendChild(img);
            resolve();
        };
        img.onerror = function() {
            reject();
        };
        img.src = "http://placehold.it/100x100?text=Image+" + i + "&v=" + Date.now();
    });
}
img { float: left; margin: 5px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.27/bluebird.min.js"></script>
<div id="container"></div>