.map函数中的异步验证



我正在使用NodeJS、Sequelize和Postgres数据库开发应用程序的后端。

当课程注册时,用户必须通知哪些组织、公司和教师将与之链接。

组织ID通过数组传递到后端,我正在尝试进行检查,以确保传递的ID存在。

到目前为止,我所做的是:

const { organizations } = req.body;
const organizationsArray = organizations.map(async (organization) => {
const organizationExists = await Organization.findByPk(organization);
if (!organizationExists) {
return res
.status(400)
.json({ error: `Organization ${organization} does not exists!` });
}
return {
course_id: id,
organization_id: organization,
};
});
await CoursesOrganizations.bulkCreate(organizationsArray);

这个链接有完整的控制器代码,相信会方便大家理解。

何时!OrganizationExists是真的,我得到的回报是组织不存在。问题是,当组织存在时,我收到以下消息错误。

Array.map()返回一个promise数组,您可以使用Promise.all()将其解析为数组。在映射中,您应该使用throw new Error()来突破映射-此错误将由Promise.all()引发,然后您可以捕获它并将错误返回给客户端(或吞下它,等等(。

这是您的模式的更正版本,解决了Promise结果。

const { organizations } = req.body;
try {
// use Promise.all to resolve the promises returned by the async callback function
const organizationsArray = await Promise.all(
// this will return an array of promises
organizations.map(async (organization) => {
const organizationExists = await Organization.findByPk(organization, { 
attributes: ['id'], // we only need the ID
raw: true, // don't need Instances
});
if (!organizationExists) {
// don't send response inside the map, throw an Error to break out
throw new Error(`Organization ${organization} does not exists!`);
}
// it does exist so return/resolve the value for the promise
return {
course_id: id,
organization_id: organization,
};
})
);
// if we get here there were no errors, create the records
await CoursesOrganizations.bulkCreate(organizationsArray);
// return a success to the client
return res.json({ success: true });
} catch (err) {
// there was an error, return it to the client
return res.status(400).json({ error: err.message }); 
}

这是一个重构版本,通过在一个查询中获取所有Organizations,然后进行检查/创建Course插入,速度会更快一些。

const { Op } = Sequelize;
const { organizations } = req.body;
try {
// get all Organization matches for the IDs
const organizationsArray = await Organization.findAll({
attributes: ['id'], // we only need the ID
where: {
id: {
[Op.in]: organizations, // WHERE id IN (organizations) 
}
},
raw: true, // no need to create Instances
});
// create an array of the IDs we found
const foundIds = organizationsArray.map((org) => org.id);
// check to see if any of the IDs are missing from the results
if (foundIds.length !== organizations.length) {
// Use Array.reduce() to figure out which IDs are missing from the results
const missingIds = organizations.reduce((missingIds, orgId) => {
if (!foundIds.includes(orgId)){
missingIds.push(orgId);
}
return missingIds;
}, []); // initialized to empty array
throw new Error(`Unable to find Organization for: ${missingIds.join(', ')}`);
}
// now create an array of courses to create using the foundIds
const courses = foundIds.map((orgId) => {
return {
course_id: id,
organization_id: orgId,
}; 
});
// if we get here there were no errors, create the records
await CoursesOrganizations.bulkCreate(courses);
// return a success to the client
return res.json({ success: true });
} catch (err) {
// there was an error, return it to the client
return res.status(400).json({ error: err.message }); 
}

如果你有一个Id数组,并且你想检查它们是否存在,你应该使用(in(运算符,这使得你只访问数据库一次,并在一次访问中获得所有记录(而不是在循环中逐个获得(,在获得这些记录后,你可以检查它们的长度,以确定它们是否都存在。

const { Op } = require("sequelize");
let foundOrgs = await Organization.findAll({
where: {
id: {
[Op.in]: organizationsArray,
}
}
});

最新更新