等待使用Promises的嵌套异步任务

时间:2014-12-02 13:28:34

标签: javascript asynchronous promise

我的代码与此类似:

// Get the data via an AJAX call
fetchAjaxData()
.then(function(data) {
    // Update or insert the data - cannot use a merge
    data.forEach(function(item) {
         updateTable(item)
         .then(function(result)) {
             // If no rows were updated, insert the item
             if (result.rowsAffected == 0) {
                 insertIntoTable(item);
                 .then(function(result)) {
                    console.log("item added");
                 });
             }
         });
    });
    return data.length;
}).then(function(l) {
    useInsertedItems(l);
});

问题是当useInsertedItems运行时,数据可能尚未插入或更新。在此之前,如何确保数据完全更新或插入?

2 个答案:

答案 0 :(得分:2)

有一篇很好的文章涵盖了你的案例。与此同时,你可以学到很多新东西! http://taoofcode.net/promise-anti-patterns/

function workMyCollection(arr) {  
    return arr.reduce(function(promise, item) {
        return promise.then(function(result) {
            return doSomethingAsyncWithResult(item, result);
        });        
    }, q());
}

答案 1 :(得分:2)

通过返回值承诺信号完成,因此您应该返回updateIteminsertIntoTable链。聚合承诺是通过Promise.all(或$ q.all,Q.all,$ .when等来完成的,具体取决于库):

更正后的代码会执行以下两项操作:

fetchAjaxData()
.then(function(data) {
    // Update or insert the data - cannot use a merge
    // map is like `each` with return values for each item
    var ps = data.map(function(item) { 
         return updateTable(item)
         .then(function(result)) {
             // If no rows were updated, insert the item
             if (result.rowsAffected == 0) {
                 return insertIntoTable(item); // note the return
                 .then(function(result)) {
                    console.log("item added");
                 });
             }
         });
    });
    return Promise.all(ps).then(function(){ return data.length; });
}).then(function(l) {
    useInsertedItems(l);
});