我有两个带有回调的异步操作。我想确保它们都成功或失败,但不能确保一个成功一个失败。这两个动作可能应该像是一个可以退回的过程?
我们来说明一下:
// In this simplified code, i assume i uploaded a file in a temporary folder.
// Every validations passed and now the goal is to move the file from temporary folder to final destination folder and to save it into database.
// This 'move' and this 'save' are my two async actions with a callback when each action is completed.
// Maybe i am not using the right way / pattern to do it, thank you for enlightening me if necessary.
myController.create = function (req, res, next) {
// I move the file from oldPath (temp directory) to newPath (final destination)
mv(oldPath, newPath, function (err) {
// If err, file is not moved i stop here, went fine. The temp directory is cleared later by the system every X period of time.
if (err) { return next(err); }
var file = new FileModel({
// some properties (name, path...)
});
// The file is now moved, need to save it into database
file.save(function (err) {
if (!err) { return next(); } // everything went fine
// If err, nothing stored in database but the file is still in final folder :o
// I could unlink the file but it still can fail and keep my file inside destination folder with no database entry.
fs.unlink(new_path, function (other_err) {
if (other_err) { return next(other_err); }
return next(err);
}
});
});
};
在上面的代码中,如果第一个动作成功,则无法保证第二个动作也将成功,并且如果失败,我可以还原(第一个动作)。这两个动作是独立的,而不是相互链接/配对和协同工作。
如果文件移动成功,则数据库中的保存也应该成功。如果无法成功保存到数据库中,那么我应该恢复到temp目录或从目标文件夹中删除该文件,以使其与数据库足够。换句话说,如果第二项操作失败,则第一个操作应失败两次。
实现此目标的好方法是什么?
编辑:我可以看到的一个解决方案是,每隔X个时间段检查最终目标文件夹中的每个文件是否在db中都有一个条目,如果没有,则删除它。
答案 0 :(得分:0)
您需要使用promise来实现这种事情,例如,您需要创建一个用户然后发送通知。因此这两个动作都是异步的,需要一个接一个地完成。
const user = {};
// This function create user and send back a id
user.createUser = (data) => {
return new Promise((resolve, reject) => {
// ...you callbacks
if (some conditions are true) {
return resolve(id);
} else {
return reject();
}
});
};
// This function finds user detail by id and send notifiaction
user.sendNotification = (id) => {
return new Promise((resolve, reject) => {
// ...you callbacks
return resolve();
});
};
user.action = async () => {
try {
const userId = await user.createUser(); // Wait for promise to resolve
await user.sendNotification(userId);
return true;
} catch (err) {
throw err;
}
};
module.exports = user;
在上面的代码中,您可以看到user.action()
函数一个接一个地调用2个单独的函数,async/await
仅适用于promise,因此我们使用关键字{ {1}}。因此,简而言之,您需要使用promise来处理这类事情。
我希望它会有所帮助。快乐编码:)