Javascript 数组在异步函数中将元素推入数组后打印为空
我是async/await的新手。当我调用函数时,第一个console.log(newArr)打印数组元素,但第二个是空数组,当我返回也是空的数组时。谁能帮帮我,我哪里出错了Javascript 数组在异步函数中将元素推入数组后打印为空,javascript,asynchronous,async-await,promise,Javascript,Asynchronous,Async Await,Promise,我是async/await的新手。当我调用函数时,第一个console.log(newArr)打印数组元素,但第二个是空数组,当我返回也是空的数组时。谁能帮帮我,我哪里出错了 const prefixPM = 'PM'; const decryptComment = (comment) => { const data = decrypt(comment).then(function (result) { const buf2 = Buff
const prefixPM = 'PM';
const decryptComment = (comment) => {
const data = decrypt(comment).then(function (result) {
const buf2 = Buffer.from(result, 'base64').toString('ascii');
return buf2;
});
return data;
};
const pmData = await queryInterface.sequelize.query(
`select ram.id, ra.name from rater_attributes ra
inner join rater_attribute_mappings ram
on ra.id = ram.raterAttributeId
inner join attributes a
on a.id = ram.by
where a.name='Project Manager'`,
{ raw: true, type: Sequelize.QueryTypes.SELECT },
);
const createPMAttributes = (ratingId, rating) => {
const newArr = [];
pmData.map(async (data) => {
const attribute = `${prefixPM}${data.name}`;
let pmComment = rating.PMComment
? await decryptComment(rating.PMComment)
: null;
pmComment = JSON.parse(pmComment);
newArr.push({
ratingId: ratingId,
raterAttributeMappingId: data.id,
rating: rating[`${attribute}`],
comment:
pmComment && pmComment[`${attribute}Comment`] ? pmComment[`${attribute}Comment`] : null,
createdAt: rating.createdAt,
updatedAt: rating.updatedAt,
});
console.log(newArr) -- this prints the newArr elements
});
console.log(newArr); -- this prints empty arr
return newArr
};
.map()
不支持异步,因此它会并行运行循环的所有迭代,在点击wait
后立即开始第二次迭代)。因此,您的第二个console.log()
正在尝试在任何回调完成之前以及在它们将数据放入newArr
之前记录newArr
下面是事情发生的顺序
pmData.map()
pmData
数组中的第一个元素并调用回调函数.map()
从.map()
.map()
然后获取pmData
数组中的下一个值并再次调用回调,即使第一个值仍在等待wait decryptComment()
.map()
将在任何回调完成之前完成
解决方案是在返回的承诺数组上使用await Promise.all()
,如果希望这些承诺并行运行,或者切换到for
循环,当点击await
时,循环将暂停
这里有一个解决方案,同时仍然并行运行所有调用。这将返回解析为值数组的承诺
const createPMAttributes = (ratingId, rating) => {
return Promise.all(pmData.map(async (data) => {
const attribute = `${prefixPM}${data.name}`;
let pmComment = rating.PMComment ?
await decryptComment(rating.PMComment) :
null;
pmComment = JSON.parse(pmComment);
return {
ratingId: ratingId,
raterAttributeMappingId: data.id,
rating: rating[`${attribute}`],
comment: pmComment && pmComment[`${attribute}Comment`] ? pmComment[
`${attribute}Comment`] : null,
createdAt: rating.createdAt,
updatedAt: rating.updatedAt,
};
}));
};
下面是一个使用for
循环的解决方案,该循环按顺序运行操作:
const createPMAttributes = async (ratingId, rating) => {
const newArr = [];
for (let data of pmData) {
const attribute = `${prefixPM}${data.name}`;
let pmComment = rating.PMComment ?
await decryptComment(rating.PMComment) :
null;
pmComment = JSON.parse(pmComment);
newArr.push({
ratingId: ratingId,
raterAttributeMappingId: data.id,
rating: rating[`${attribute}`],
comment: pmComment && pmComment[`${attribute}Comment`] ? pmComment[
`${attribute}Comment`] : null,
createdAt: rating.createdAt,
updatedAt: rating.updatedAt,
});
}
return newArr;
};
这里有一个一般提示。仅当您实际想要使用它生成的返回数组时才使用
.map()
。如果您要做的只是使用它来迭代数组,那么请改用for
循环,因为它更灵活并且是异步的
而且,如果因为使用了wait
,而将.map()
回调为async
,那么您将并行运行所有操作,并且知道何时完成的唯一方法是对回调生成的承诺数组使用Promise.all()
。请记住,每个async
函数都会返回一个承诺-始终。因此,让resultArr=someArr.map(async=>{}{}})
将始终生成一个承诺数组,告诉您事情实际完成的时间。谢谢您的回答。我做了更改,但是当我调用函数const arr=wait createPMAttributes(pmRatingId,rating)时;控制台日志(arr);它打印[undefined,undefined,undefined,undefined,undefined,undefined],而不是数组elements@habiba-看起来我的版本中没有所有的更改。如果您使用的是我的第一个版本,那么请查看我的return
在哪里。非常感谢!你是最棒的!它就像一个符咒但我有两个函数,一个用于PMattributes,另一个用于archAttributes,我想把这两个函数的评级推到一个arr中,然后遍历该数组并将对象插入数据库,你知道我怎么做吗?@habiba-我不明白。您想将两个函数合并为一个生成一个结果的函数,还是有两个单独的函数,从每个函数中得到一个结果数组,然后将这两个数组合并?仅供参考,这听起来有点像一个新问题。