如果我需要对几个集合执行两个或三个不同的操作,有没有比将find/update
操作链接在一起更好的方法?例如:
db.collection('contactinfos').findOneAndUpdate(
{ _id: ObjectID(contactID) },
{ $set: { sharedWith } }
).then(response => {
db.collection('users').update(
{ _id: { $in: sharedWith.map(id => ObjectID(id)) } },
{ $addToSet: { hasAccessTo: contactID } },
{ multi: true }
).then(response => {
db.collection('users').update(
{ _id: { $in: notSharedWith.map(id => ObjectID(id)) } },
{ $pull: { hasAccessTo: contactID } },
{ multi: true }
).then(response => {
return res.send({ success: true });
}).catch(err => {
logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err);
return res.status(400).send({ reason: 'unknown' });
});
}).catch(err => {
logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err);
return res.status(400).send({ reason: 'unknown' });
});
}).catch(err => {
logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err);
return res.status(400).send({ reason: 'unknown' });
});
它看起来很混乱,必须有一些更好的方法。此外,如果在阻止其他findOneAndUpdate
运行的第一个update
之后出现错误,则跨文档的数据将不一致。这些文档包含对其他文档的ID引用,以便更快地查找。
此外,有没有办法捕捉承诺链中的所有错误?
答案 0 :(得分:1)
从你的回调地狱我可以看到你不在任何地方使用response
方法的.then()
参数。如果您不需要一个查询的结果来执行另一个查询,请考虑使用Promise.all()
方法:
const updateContactInfo = db.collection('contactinfos')
.findOneAndUpdate(
{ _id: ObjectID(contactID) },
{ $set: { sharedWith } }
);
const updateUsers = db.collection('users')
.update(
{ _id: { $in: sharedWith.map(id => ObjectID(id)) } }, //hint: use .map(ObjectId) instead.
{ $addToSet: { hasAccessTo: contactID } },
{ multi: true }
);
const updateUsers2 = db.collection('users')
.update(
{ _id: { $in: notSharedWith.map(id => ObjectID(id)) } }, //hint: use .map(ObjectId) instead.
{ $pull: { hasAccessTo: contactID } },
{ multi: true }
);
Promise
.all([updateContactInfo, updateUsers, updateUsers2])
.then((values) => {
const updateContactInfoResult = values[0];
const updateUsersResult = values[1];
const updateUsers2Result = values[2];
return res.send({ success: true });
})
.catch((reason) => {
logger.error(`msg`, reason);
return res.status(400).send({ reason: 'unknown' });
});
只有当所有承诺都解决后, Promise.all()
才会继续执行.then()
,否则它将落入.catch()
方法。在错误处理方面,您可以轻松地链接多个.catch()
方法,这很好地解释了here。
如果您不能有任何数据不一致,请:
如果可以接受,请每1kk次说一次,确保在应用程序的逻辑中检查它的一致性。