[英]node.js chain multiple promises (with mongoose)
The following is a typical promise function that I am dealing with. 以下是我正在处理的典型承诺函数。
var _delete = function(t, id) {
return Promise.cast(Event.find({where: {id: id}}, {transaction: t}))
.then(function(d){
if (d) {
// ------- (*)
return Promise.cast(d.updateAttributes({status: -1}, {transaction: t}))
.then(function(){
// do inventory stuff
return Promise.cast(Inventory.update({}).exec())
.then(function(d){
// do something
})
}).then(function(){
// do product stuff
return Promise.cast(Product.update({}).exec())
.then(function(d){
// do something
})
})
} else {
return Promise.reject('this transaction list does not exist');
}
});
};
This looks ok until when I am dealing with more complicated update / creates the code will become really messy. 这看起来不错,直到我处理更复杂的更新/创建代码将变得非常混乱。
Currently what I am doing with promise is that 1. I have a lot of useless return true statements and the only purpose is to go to next .then statement 2. promise are programmed in a nested style. 目前我正在承诺的是1.我有很多无用的返回真实语句,唯一的目的是转到下一个。然后声明2. promise以嵌套方式编程。 also the input arguments are usually complicated and has more then 1 arguments so that I cannot do something like this 输入参数通常很复杂,并且有超过1个参数,所以我不能做这样的事情
.then(fun1).then(fun2)
... etc ......等
which makes me unable to 'tap'
the .then
statement to enable/disable a functionality. 这使我无法'tap'
.then
语句来启用/禁用功能。
So my questions is how do I do this correctly? 所以我的问题是如何正确地做到这一点? Thanks.. 谢谢..
the following is the really ugly things that I am talking about.... 以下是我所说的非常丑陋的事情....
var _process = function(t, tid) {
var that = this;
return Promise.cast(Usermain.find({where: {transaction_id: tid}}))
.bind({}) // --- (*)
.then(function(d){
this.tmain = d;
return true; // ---- do nothing, just go to next thennable (is this correct)
}).then(function(){
return Promise.cast(Userlist.findAndCountAll({where: {transaction_id: tid}}))
}).then(function(d){
this.tlist = d;
return true; // ---- do nothing, just go to next thennable (is this correct)
}).then(function(){
if (this.tmain.is_processed) {
return Promise.reject('something is wrong');
}
if (this.tlist.count !== this.tmain.num_of_tran) {
return Promise.reject('wrong');
}
return Promise.resolve(JSON.parse(JSON.stringify(this.tlist.rows)))
.map(function(d){
if (d.is_processed) return Promise.reject('something is wrong with tran list');
return true; // goto next then
});
}).then(function(){
return Promise.cast(this.tmain.updateAttributes({is_processed: 1}, {transaction: t}));
}).then(function(){
return Promise.resolve(this.tlist.rows)
.map(function(d){
var tranlist = JSON.parse(JSON.stringify(d));
return Promise.cast(d.updateAttributes({is_processed: 1, date_processed: Date.now()}, {transaction: t}))
.then(function(d){
if (!d) {
return Promise.reject('cannot update tran main somehow');
} else {
if (tranlist.amount < 0) {
return Usermoney._payBalance(t, tranlist.user_id, -tranlist.amount);
} else {
return Usermoney._receiveBalance(t, tranlist.user_id, tranlist.amount);
}
}
});
});
});
}
You can do two things: 你可以做两件事:
then
callbacks Unnest then
回调 In this case, unnesting could do the following (assuming you don't need closures in your commented sections): 在这种情况下,可以执行以下操作(假设您的注释部分中不需要关闭):
function _delete(t, id) {
return Promise.cast(Event.find({where: {id: id}}, {transaction: t}))
.then(function(d){
if (d) {
return Promise.cast(d.updateAttributes({status: -1}, {transaction: t}));
else
throw new Error('this transaction list does not exist');
})
.then(function(){
// do inventory stuff
return Promise.cast(Inventory.update({}).exec())
})
.then(function(d){
// do something
})
.then(function(){
// do product stuff
return Promise.cast(Product.update({}).exec())
})
.then(function(d){
// do something
});
}
In my projects I use Async.js 在我的项目中,我使用Async.js
I think you need to decompose your _process
method into small actions 我认为你需要将_process
方法分解为_process
waterfall
pattern might be used here 依赖于先前操作的结果的操作 - 异步waterfall
模式可能在此处使用 Here is an example from my app: 以下是我的应用中的示例:
async.waterfall([
function findUser(next) {
Users.findById(userId, function (err, user){
if(err) {
next(new Error(util.format('User [%s] was not found.', userId)));
return;
}
next(null, user);
});
},
function findUserStoriesAndSurveys(user, next) {
async.parallel([
function findStories(callback) {
// find all user stories
Stories.find({ UserGroups: { $in : user.Groups } })
.populate('Topic')
.populate('Episodes')
.exec(function(err, stories) {
if(err) {
callback(err);
return;
}
callback(null, stories);
});
},
function findSurveys(callback) {
// find all completed surveys
Surveys.find({
User: user
}).exec(function(err, surveys) {
if(err) {
callback(err);
return;
}
callback(null, surveys);
});
}
],
function(err, results) {
if(err) {
next(err);
return;
}
next(null, results[0], results[1]);
});
},
function calculateResult(stories, surveys, next) {
// do sth with stories and surveys
next(null, { /* result object */ });
}
], function (err, resultObject) {
if (err) {
res.render('error_template', {
status: 500,
message: 'Oops! Server error! Please reload the page.'
});
}
res.send(/* .... */);
});
Please refer to Async docs for a custom process, it really does contain a lot of common patterns, I also use this library in my client JavaScript. 请参阅Async文档以获取自定义过程,它确实包含许多常见模式,我也在我的客户端JavaScript中使用此库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.