Node.js异步编程求助:获取帖子后关联用户详情失败
解决异步添加用户详情到帖子的Promise过早resolve问题
你的判断完全正确——addUserDetails函数里的resolve(posts)确实过早执行了。posts.map内部的fetchUser是异步操作,这些请求还没完成、还没把userDetails挂载到对应post对象上,你就已经把原始posts数组返回了,所以后续打印自然看不到预期的userDetails字段。
修正方案
核心思路是等待所有异步获取用户的操作完成后,再返回更新后的posts数组,这里用Promise.all来实现最直接:
方案1:将addUserDetails改为async函数
const fetch = require('node-fetch'); // Async function to retrieve the user details for a given user Id const fetchUser = async (userId) => { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`); return response.json(); }; const addUserDetails = async (posts) => { // 为每个post创建一个异步任务:获取用户并挂载到post对象 const updateTasks = posts.map(async (post) => { const userDetails = await fetchUser(post.userId); post.userDetails = userDetails; return post; }); // 等待所有异步任务完成 await Promise.all(updateTasks); return posts; }; // Async function to retrieve all posts const fetchPosts = async () => { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); return response.json(); }; fetchPosts() .then(posts => addUserDetails(posts)) .then(postsWithUserDetails => { console.log(postsWithUserDetails[0]); }) .catch(err => console.log(err));
方案2:用Promise.all替代手动创建Promise
如果你不想用async函数,也可以直接通过Promise.all封装所有异步请求:
const addUserDetails = (posts) => { // 生成所有获取用户并更新post的Promise数组 const promises = posts.map(post => fetchUser(post.userId) .then(userDetails => { post.userDetails = userDetails; return post; }) ); // 等待所有Promise完成后返回结果 return Promise.all(promises); };
为什么原代码会失败?
原代码中,posts.map只是触发了一系列异步请求,但并没有等待这些请求完成。resolve(posts)会在map执行完毕后立刻调用——这时候所有fetchUser请求还处于pending状态,userDetails根本还没被添加到post对象上,所以后续拿到的是未修改的原始posts数组。
内容的提问来源于stack exchange,提问作者Nemil Sheriff
相关产品推荐
相关产品推荐

