2017-08-08 113 views
4

我想在我的forEach循環之後運行代碼。如何在node.js中完成異步函數後運行一個函數?

myPosts.forEach(function(post) { 
    getPostAuthor(post.authorID, function(postAuthor) { 
     post.author = postAuthor; 
    } 
}); 

res.render('index', { 
    posts: myPosts 
}); 
res.end(); 

在上述第一res.render運行和之後的forEach代碼填充post.author

+0

的forEach不是異步。 getPostAuthor是。 –

+0

不,但我敢打賭'getPostAuthor()'是。 – jakerella

+0

我的意思是forEach的函數 –

回答

4

而是地圖諾言比用foreach迭代,然後使用Promise.all:

Promise.all(
myPosts.map(function(post) { 
    return new Promise(function(res){ 
    getPostAuthor(post.authorID, function(postAuthor) { 
     post.author = postAuthor; 
     res(postAuthor); 
    }); 
    }); 
}) 
).then(function(authors){ 

    res.render('index', { 
    posts: myPosts 
    }); 
    res.end(); 

}); 
+0

爲什麼它是低估的:/?!? –

+0

您應該在'.then()'處理程序中顯示'res.render()',因爲這是OP試圖完成的任務(在異步操作完成後獲取渲染)。順便說一下,我沒有倒下 - 不知道爲什麼有人這樣做。 – jfriend00

0

你可以這樣做2種方式,你可以創建/使用Promise或使用的計數方法。

計數方法:

var numComplete = 0; 
var done = function() { 
    if(numComplete >= myPosts.length) { 
     // Code to run once finished 
    } 
}; 

myPosts.forEach(function(post) { 
    getPostAuthor(post.authorID, function(postAuthor) { 
     post.author = postAuthor; 
     numComplete++; 
     done(); 
    } 
}); 
2

您可以創建承諾的數組,然後監聽使用Promise.all全部完工。

const promises = []; 

myPosts.forEach(function(post) { 
    const promise = new Promise((resolve) => { 
     getPostAuthor(post.authorID, function(postAuthor) { 
      post.author = postAuthor; 
      resolve(); // complete the current promise 
     } 
    }); 

    promises.push(promise); 
}); 

Promise.all(promises).then(() => { 
    res.render('index', { 
    posts: myPosts 
    }); 
    res.end(); 
}); 
+1

你是那裏的90%,然後你沒有在'Promise.all()'回調中放置'res.render()'。 – jfriend00

0

你可以使用一個第三方的lib像異步。

例子:

import each from 'async/each'; 

var elements = [1, 2, 3, 4, 5, 6]; 

each(elements, function(el, next) { 
    console.log('Processing element ' + el); 
    callAsyncFunction(next); //your async function should accept a callback 
}, function(err){ 
    //this is your ending function. It'll be called after all elements have been processed 
    if(err) { 
     console.log('A file failed to process'); 
    } else { 
     console.log('Async processing is finished.'); 
    } 
}); 

您的代碼應該是這樣的:

each(myPosts, function(post, next) { 
    getPostAuthor(post.authorID, function(postAuthor) { 
     post.author = postAuthor; 
     next() 
    }); 
}, function(err) { 
    if (!err) { 
     res.render('index', { 
      posts: myPosts 
     }); 
     res.end(); 
    } 
}); 
0

你可以嘗試用async/awaitfor loop

const sleep = timeout => new Promise(resolve => setTimeout(() => resolve(), timeout)); 
 
const myPosts = [1,2,3]; 
 

 
const fetchPosts = async() => { 
 
    for (let post_id of myPosts) { 
 
    await sleep(1000); // simulate fetch post 
 
    console.log('post:', post_id); 
 
    } 
 

 
    console.log('done!'); 
 
}; 
 

 
fetchPosts();

0

使用async.eachOf到迭代數組和應用異步函數:

async.eachOf(myPosts, function(post, it, callback){ 

    // apply async function on each element 
    getPostAuthor(post.authorID, function(postAuthor) { 
     post.author = postAuthor; 
     return callback(); 
    }); 

}, function(err){ 
    // final callback when flow is finished 
    res.render('index', { 
     posts: myPosts 
    }); 
    return res.end(); 
}); 

參見異步文檔:https://caolan.github.io/async/docs.html

相關問題