猫鼬异步/等待
Posted
技术标签:
【中文标题】猫鼬异步/等待【英文标题】:mongoose async / await 【发布时间】:2018-08-30 22:10:21 【问题描述】:我正在使用 mongodb 和 apollo 服务器学习 node js 和 graphql,下面的代码按预期工作,但是我感觉代码可以改进。这是我的 graphql 解析器上的 sn-p:
Mutation:
...,
createJob: async (parent, args, Customer, Employee, Job ) =>
const newJob = await new Job(args).save();
newJob.assigned.map(async(employeeId) =>
const assignedEmployee = await Employee.findById(employeeId);
assignedEmployee.jobsHistory.push(newJob._id);
await assignedEmployee.save()
);
const customer = await Customer.findById(newJob.customer);
customer.jobs.push(newJob._id);
await customer.save();
return newJob;
正如我所说,代码按预期工作,但看着许多等待,我不能停下来想知道是否可以进行改进。任何帮助将不胜感激
【问题讨论】:
为什么你认为很多await
s 会不好?
无论调用createJob
是否理解它返回一个承诺并相应地处理它? (map
肯定不会,所以这是个问题——就像使用 map
而不对它返回的数组做任何事情一样。)
实际上你甚至错过了一个:assigned.map(…)
内部创建的承诺永远不会等待。您需要将其包装在 await Promise.all(…)
中。
【参考方案1】:
多个await
s 只是async
/await
的本质。你必须标记每一个你等待异步操作发生的地方。
该代码的主要问题是您忽略了map
的返回值,因此忽略了您传递map
的async
函数创建的promise 的结果。 任何当您调用map
并且不对它的返回值做任何事情时,您就知道您使用了错误的工具(当您不需要数组@987654329 时使用forEach
@returns) 或做其他错误。
假设您希望员工更新并行运行,并且您希望在更新客户之前等待所有更新完成,您希望 await Promise.all(...)
数组 map
返回:
createJob: async (parent, args, Customer, Employee, Job ) =>
const newJob = await new Job(args).save();
await Promise.all(newJob.assigned.map(async(employeeId) => // ***
const assignedEmployee = await Employee.findById(employeeId);
assignedEmployee.jobsHistory.push(newJob._id);
await assignedEmployee.save();
));
const customer = await Customer.findById(newJob.customer);
customer.jobs.push(newJob._id);
await customer.save();
return newJob;
但大概不需要在找到客户之前等待员工更新,因此我们可以通过在员工更新的同时搜索客户来稍微改进:
createJob: async (parent, args, Customer, Employee, Job ) =>
const newJob = await new Job(args).save();
const customerPromise = Customer.findById(newJob.customer); // ***
await Promise.all(newJob.assigned.map(async(employeeId) =>
const assignedEmployee = await Employee.findById(employeeId);
assignedEmployee.jobsHistory.push(newJob._id);
await assignedEmployee.save();
));
const customer = await customerPromise; // ***
customer.jobs.push(newJob._id);
await customer.save();
return newJob;
【讨论】:
感谢您的详细回答,我想我的痒是由于该地图操作员缺少返回!只是一个快速的,我似乎看不出你的第一个代码和第二个代码之间的不同。第二个代码似乎与第一个代码运行相同,除了将 Customer promise 分配给一个 const @scubadude:第一个开始所有员工的工作,等待它完成,然后找到客户,更新并保存。第二个开始寻找客户,在运行时启动所有员工工作,等待所有员工工作完成,等待寻找客户完成,然后更新客户。正如我在回答中所说,它运行查找客户的操作与员工操作并行而不是在他们之后连续运行,可能会节省几毫秒的经过时间。 :-) 感谢详细解答以上是关于猫鼬异步/等待的主要内容,如果未能解决你的问题,请参考以下文章