基本上,我有一个代码来批准订单代码,方法是将用户输入的优惠券应用到订单交易中:
var Order = require('../models/order');
var Product = require('../models/product');
var Coupon = require('../models/coupon');
var _ = require('lodash');
exports.approveOrder = function(req, res) {
var tempProducts;
var tempCoupon;
var orderNbr = req.params.OrderNbr;
if (orderNbr != undefined && orderNbr != '')
{
Order.findOne({ OrderNbr: orderNbr }).exec()
.then(function(order) {
if (order == undefined) {
throw "Order " + orderNbr + " does not exist.";
}
else {
if (order.OrderLines.length <= 0) throw "Ensure your Order has at least one order line.";
if (req.body.CouponCode != undefined && req.body.CouponCode != '') {
// ***********************************************
// Want to refactor this following codes into some functions
// ***********************************************
Coupon.findOne({ CouponCode: req.body.CouponCode }).exec()
.then(function(coupon) {
if (coupon == undefined) {
throw "Coupon " + req.body.CouponCode + " does not exist.";
}
else {
if (coupon.Qty > 0 && (coupon.ValidFrom <= new Date() && coupon.ValidTo >= new Date())) {
coupon.Qty -= 1;
tempCoupon = coupon;
var prodNbrs = _.map(order.OrderLines, 'ProdNbr');
return Product.find({ ProdNbr: { $in : prodNbrs } }).exec();
}
else {
throw "Coupon " + coupon.CouponCode + " is not valid.";
}
}
})
.then(function(products) {
var prodNbrs = _.map(order.OrderLines, 'ProdNbr');
var totalQtyPerProd = 0;
_.forEach(products, function(product) {
totalQtyPerProd = _.sumBy(order.OrderLines, function(line) {
if (product.ProdNbr == line.ProdNbr) return line.Qty;
})
if (product.QtyOnHand - totalQtyPerProd < 0) throw "Product " + product.ProdNbr + " has insufficient quantity on hand.";
_.remove(prodNbrs, function(nbr) { return nbr == product.ProdNbr });
product.QtyOnHand -= totalQtyPerProd;
var totalDiscount = tempCoupon.Value / order.OrderLines.length;
if (tempCoupon.IsPercentage) {
totalDiscount = 1 - (tempCoupon.Value / 100);
}
_.forEach(order.OrderLines, function(line) {
if (line.ProdNbr == product.ProdNbr) {
line.UnitPrice = product.UnitPrice;
line.Amount = (line.Qty * line.UnitPrice) - totalDiscount;
if (line.Amount < 0) line.Amount = 0;
if (tempCoupon.IsPercentage) {
line.Amount = (line.Qty * line.UnitPrice) * totalDiscount;
}
}
})
})
if (prodNbrs.length > 0) throw "Product " + prodNbrs[0] + " does not exist.";
tempProducts = products;
order.CouponCode = tempCoupon.CouponCode;
order.Status = 'S';
return order.save();
})
.then(function() {
return tempCoupon.save();
})
.then(function() {
_.forEach(tempProducts, function(product) {
product.save()
.then(function() {
})
.catch(function(err) {
if (err) res.status('500').jsonp({ error: err });
});
})
res.status('200').jsonp({ information: "Order "+ order.OrderNbr +" has been submitted successfully." });
})
.catch(function(err) {
if (err) res.status('500').jsonp({ error: err });
});
}
}
})
.catch(function(err) {
if (err) res.status('500').jsonp({ error: err });
});
}
else {
res.status('500').jsonp({ error: "Order Number must be specified." });
}
};
我想分别编码代码&#39;然后&#39;子句进入一些功能:
我尝试使用局部变量来保留找到的优惠券,不幸的是,如果变量是在findOne()方法之外的话,那么变量将是未定义的,所以在这段代码中我使用了很多很长的&#39;然后#39;在findOne()
中有什么想法吗?
答案 0 :(得分:1)
我建议您使用瀑布方法来使用async库。从本质上讲,通过使用回调,它将允许您在没有嵌套的情况下拥有更平坦的结构。
这样的事情:
var async = require('async');
var findCoupons = function(cb) {
//do something
cb(null, 'success');
}
var updateOrders = function(data, cb) {
//do something
console.log(data); //success
cb(null, 'etc.');
}
...
async.waterfall([
findCoupons,
updateOrders,
updateCoupon,
confirmMessage
], function(err, result) {
//all functions have finished running, do something.
});
答案 1 :(得分:1)
您使用&#34;然后链#34;很好。 我将重构代码,创建在链中使用的分离函数,如下所示:
var saveProducts = function() {
_.forEach(tempProducts, function(product) {
product.save()
.then(function() {
})
.catch(function(err) {
if (err) res.status('500').jsonp({ error: err });
});
})
res.status('200').jsonp({ information: "Order "+ order.OrderNbr +" has been submitted successfully." });
}
var saveCoupon = function() {
return tempCoupon.save();
}
var products = function(products) {
var prodNbrs = _.map(order.OrderLines, 'ProdNbr');
var totalQtyPerProd = 0;
_.forEach(products, function(product) {
totalQtyPerProd = _.sumBy(order.OrderLines, function(line) {
if (product.ProdNbr == line.ProdNbr) return line.Qty;
})
if (product.QtyOnHand - totalQtyPerProd < 0) throw "Product " + product.ProdNbr + " has insufficient quantity on hand.";
_.remove(prodNbrs, function(nbr) { return nbr == product.ProdNbr });
product.QtyOnHand -= totalQtyPerProd;
var totalDiscount = tempCoupon.Value / order.OrderLines.length;
if (tempCoupon.IsPercentage) {
totalDiscount = 1 - (tempCoupon.Value / 100);
}
_.forEach(order.OrderLines, function(line) {
if (line.ProdNbr == product.ProdNbr) {
line.UnitPrice = product.UnitPrice;
line.Amount = (line.Qty * line.UnitPrice) - totalDiscount;
if (line.Amount < 0) line.Amount = 0;
if (tempCoupon.IsPercentage) {
line.Amount = (line.Qty * line.UnitPrice) * totalDiscount;
}
}
})
})
if (prodNbrs.length > 0) throw "Product " + prodNbrs[0] + " does not exist.";
tempProducts = products;
order.CouponCode = tempCoupon.CouponCode;
order.Status = 'S';
return order.save();
}
var getProducts = function(coupon) {
if (coupon == undefined) {
throw "Coupon " + req.body.CouponCode + " does not exist.";
}
else {
if (coupon.Qty > 0 && (coupon.ValidFrom <= new Date() && coupon.ValidTo >= new Date())) {
coupon.Qty -= 1;
tempCoupon = coupon;
var prodNbrs = _.map(order.OrderLines, 'ProdNbr');
return Product.find({ ProdNbr: { $in : prodNbrs } }).exec();
}
else {
throw "Coupon " + coupon.CouponCode + " is not valid.";
}
}
}
exports.approveOrder = function(req, res) {
var tempProducts;
var tempCoupon;
var orderNbr = req.params.OrderNbr;
if (orderNbr != undefined && orderNbr != '')
{
Order.findOne({ OrderNbr: orderNbr }).exec()
.then(function(order) {
if (order == undefined) {
throw "Order " + orderNbr + " does not exist.";
}
else {
if (order.OrderLines.length <= 0) throw "Ensure your Order has at least one order line.";
if (req.body.CouponCode != undefined && req.body.CouponCode != '') {
// ***********************************************
// Want to refactor this following codes into some functions
// ***********************************************
Coupon.findOne({ CouponCode: req.body.CouponCode }).exec()
.then(getProducts)
.then(products)
.then(saveCoupon)
.then(saveProducts)
.catch(function(err) {
if (err) res.status('500').jsonp({ error: err });
});
}
}
})
.catch(function(err) {
if (err) res.status('500').jsonp({ error: err });
});
}
else {
res.status('500').jsonp({ error: "Order Number must be specified." });
}
};
每个函数的结果将传递给链中的下一个
我建议使用最佳做法承诺