あなたは.exec()
は約束を返すことを認識すると、次のことができます。
- は、望ましい平坦化を達成し、コードをより読みやすくします。
- "成功"コードの間でエラーを処理する必要性を回避します。
- 端末の.then()または.catch()エラーを処理します。
さらに、x in y
条件ごとに意味のあるエラーが発生する(より簡単に)ことができます。
素直に、あなたが書くことができる:
function _addFriend(requesterId, targetId) {
return User.findById(requesterId).exec().then(requester => {
if (targetId in requester.friends) {
throw new Error('target is already a friend');
}
if (targetId in requester.sentfriendRequests) {
throw new Error('friend request already sent to target');
}
if (targetId in requester.friendRequests) {
throw new Error('target already sent a friend request to requester');
}
requester.sentfriendRequests = requester.sentfriendRequests.concat([targetId]); // or just .push()?
return requester.save();
}).then(() => {
return User.findById(targetId).exec().then(target => {
target.friendRequests = target.friendRequests.concat([requesterId]); // or just .push()?
return target.save();
});
});
}
は、流れを制御するリターンの必要性に注意してください。
しかし、あなたはもっと良くすることができます。上記のように、要求されたものは成功し、ターゲットのものは失敗し、dbの不一致が生じます。だからあなたが本当に望むのは、dbトランザクションで、どちらも起こるかどうかを保証することではありません。 Mongooseは間違いなくトランザクションを提供しますが、部分利益のようなトランザクションを提供するためにクライアント側で何かを行うことができます。ここで
function _addFriend(requesterId, targetId) {
return Promise.all([User.findById(requesterId).exec(), User.findById(targetId).exec()]).then(([requester, target]) => { // note destructuring
if (targetId in requester.friends) {
throw new Error('target is already a friend');
}
if (targetId in requester.sentfriendRequests) {
throw new Error('friend request already sent to target');
}
if (targetId in requester.friendRequests) {
throw new Error('target already sent a friend request to requester');
}
requester.sentfriendRequests = requester.sentfriendRequests.concat([targetId]);
target.friendRequests = target.friendRequests.concat([requesterId]);
return requester.save().then(() => {
return target.save();
});
});
}
、あなたはまだ最初に保存すること(そう)の状況が成功すると保存第二に障害が発生したが、少なくとも、あなたが依頼者とターゲットの両方が存在しない限り、絶対に何も起こらない保証を持って得ることができます。どちらの場合も
次のように、呼び出し:
_addFriend(requesterId, targetId).then(function() {
// do whatever on success
}, function(error) {
// do whatever on error
});
をあなたはライブ環境でのエラーメッセージを使用しない場合でも/デバッグをテストするとき、彼らは非常に有用である可能性があります。それらをチェックしてください - 私はそれらを間違えたかもしれません。
最初の 'exec'コールバックに' err'パラメータは必要ないのですか? – Bergi
'.then(err => {if(err)throw err})'約束でそれが必要なように見えない – Bergi