JavaScript:同步执行一系列承诺

时间:2015-11-01 17:10:15

标签: javascript loops promise

我有一个请求承诺,我需要执行一个循环,如:

RealmMigration migration = new RealmMigration() {
    @Override
    public long execute(Realm realm, long version) {
        Table table = realm.getTable(Dog.class);
        table.convertColumnToNullable(table.getColumnIndex("name"));
        return 1;
    }
};

问题是我永远不知道数组中有多少元素,所以我需要一个动态模式。是否可以混合同步和异步世界,以便一时只有一个请求处于活动状态(序列不重要)?

1 个答案:

答案 0 :(得分:11)

一种循环迭代数组的经典方法,在每个数组元素上调用一些异步操作是使用.reduce()并链接到初始保证,如下所示:

  

问题是我永远不知道数组中有多少元素,所以   我需要一个动态模式。

您可以使用promises链接对其进行排序。为此,使用.reduce()来迭代数组是很有用的,因为它提供了正确的迭代类型,可以在迭代数组时跟踪累积值(在这种情况下是一个promise)。您可以使用额外的变量使几乎任何数组迭代方案都工作,这与.reduce()很好地对齐:

var ids = [1,2,3,4,5,6,7];
ids.reduce(function(p, item) {
    return p.then(function() {
        return doPromise(item);
    });
}, Promise.resolve()).then(function(results) {
    // all done here with array of results
});

这将一个已解决的承诺传递给ids.reduce()作为承诺链的负责人。然后,它在该promise上执行.then()并为数组中的每个项返回一个新的promise(通过.reduce()回调)。 .reduce()调用的最终结果将是一个承诺,当解决时意味着整个链完成。

理解这一点的关键是要记住p.then()返回一个新的承诺,所以我们只是在每个新承诺上调用.then(),并且我们从每个.then()的每个操作中返回承诺处理程序。这具有将所有承诺链接在一起成为一个顺序链的效果。

  

是否可以混合同步和异步世界,以便只有一个   请求现在处于活动状态(序列不重要)?

我不确定你的意思是“混合同步和异步世界”。确保一次只有一个请求在飞行中的方法是将它们一个接一个地排序,以便下一个请求仅在前一个请求完成时开始。这也恰好保证了执行顺序,即使你说在这种情况下并不重要,但它是确保一次只有一个在飞行中的副产品。

而且,这是一个工作片段:

function log(msg) {
    var d = document.createElement("div");
    d.textContent = msg;
    document.body.appendChild(d);
}

function doPromise(x) {
    return new Promise(function(resolve) {
        setTimeout(function() {
            log(x);
            resolve(x);
        }, Math.floor(Math.random() * 1000));
    });
}

var ids = [1,2,3,4,5,6,7];
ids.reduce(function(p, item) {
    return p.then(function() {
        return doPromise(item);
    });
}, Promise.resolve()).then(function() {
    // all done here
    log("all done");
});