Promise数组无数据问题求助:异步操作未正确存入数组
问题分析与解决方案
原.then()写法的问题
你当前的代码里,Promise.all(newJoinsPromiseArray)会在循环里的异步操作完成前就执行——因为newJoinElement.save()是异步的,.then里的push要等save完成后才会执行,但此时Promise.all已经跑完了,数组自然是空的。
另外,你不需要在save的回调里push Promise,应该把整个异步流程的Promise直接存入数组。
修正后的.then()写法
export const create = (req, res, next) => { const newJoinsPromiseArray = []; for (const worker of req.body.workers){ const newJoinElement = new JoinTable(null, req.body.contact_id, worker.value); // 把完整的Promise链存入数组:save成功后执行findByID const promiseChain = newJoinElement.save() .then((result) => { return JoinTable.findByID(result[0].insertId); }) .catch(err => { throw err; // 把错误抛给Promise.all统一处理 }); newJoinsPromiseArray.push(promiseChain); } Promise.all(newJoinsPromiseArray) .then((values) => { console.log(values); res.json({data: values}); }) .catch(err => { res.json({message: err}); }); }
async/await写法的问题
你用了newJoinsPromiseArray.concat(joinElementByID),但concat是返回新数组,不会修改原数组,所以原数组一直是空的。另外,建议统一处理错误,避免循环里单独返回响应导致重复响应的问题。
修正后的async/await串行版本
export const create = async (req, res, next) => { const newJoinsArray = []; for (const worker of req.body.workers){ const newJoinElement = new JoinTable(null, req.body.contact_id, worker.value); try{ const savedResult = await newJoinElement.save(); const joinElementByID = await JoinTable.findByID(savedResult[0].insertId); // 用push修改原数组,db.execute返回[rows, fields],如需数据可取joinElementByID[0] newJoinsArray.push(joinElementByID); } catch (e){ return res.json({message: e}); // 遇到错误直接返回,终止后续执行 } } console.log(newJoinsArray); res.json({data: newJoinsArray}); }
更高效的async/await并行版本
export const create = async (req, res, next) => { try { // 生成所有异步操作的Promise数组 const promiseArray = req.body.workers.map(worker => { const newJoinElement = new JoinTable(null, req.body.contact_id, worker.value); return newJoinElement.save() .then(savedResult => JoinTable.findByID(savedResult[0].insertId)); }); // 并行执行所有Promise const newJoinsArray = await Promise.all(promiseArray); console.log(newJoinsArray); res.json({data: newJoinsArray}); } catch (e) { res.json({message: e}); } }
关键注意点
- 异步时机:
Promise.all必须等所有要执行的Promise都存入数组后再调用,不能在异步回调填充数组的同时提前执行。 - 数组操作:
concat不修改原数组,添加元素要用push或直接赋值。 - 错误处理:尽量统一捕获错误,避免循环内单独返回响应导致重复响应。
内容的提问来源于stack exchange,提问作者zichyboy
相关产品推荐
相关产品推荐

