Bạn sẽ phải lồng các lệnh gọi của mình để xóa id sản phẩm khỏi mô hình khác. Ví dụ:trong cuộc gọi của bạn để xóa sản phẩm khỏi Sản phẩm
bộ sưu tập, bạn cũng có thể thực hiện một cuộc gọi khác để xóa tham chiếu khỏi Đối tác
mô hình trong cuộc gọi lại kết quả. Loại bỏ sản phẩm theo mặc định sẽ loại bỏ các tham chiếu của nó đối với Chiến dịch
Người mẫu.
Đoạn mã sau cho thấy trực giác ở trên:
var campSchema = require('../model/camp-schema');
router.post('/removeProduct', function (req, res) {
campSchema.Product.findOneAndRemove({ _id: req.body.productId }, function (err, response) {
if (err) throw err;
campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } },
function (err, res){
if (err) throw err;
res.json(res);
}
);
});
});
Để loại bỏ các chiến dịch được liên kết, bạn có thể cần thêm một thao tác xóa có trong id chiến dịch được liên kết với một id sản phẩm nhất định. Hãy xem xét vụ tấn công bẩn thỉu sau đây có thể có khả năng trao cho bạn vé một chiều đến địa ngục gọi lại nếu không cẩn thận với lồng gọi lại:
router.post('/removeProduct', function (req, res) {
campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
{ new: true },
function (err, product) {
if (err) throw err;
campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } },
function (err, res){
if (err) throw err;
var campaignList = product.campaign
campSchema.Campaign.remove({ "_id": { "$in": campaignList } })
.exec(function (err, res){
if (err) throw err;
res.json(product);
})
}
);
}
);
});
Mặc dù nó hoạt động nhưng có thể tránh được cạm bẫy tiềm ẩn ở trên bằng cách sử dụng async / await hoặc async
thư viện. Nhưng trước hết, để bạn hiểu rõ hơn về việc sử dụng nhiều lệnh gọi lại với async
mô-đun, hãy minh họa điều này bằng một ví dụ từ Seven Những điều bạn nên ngừng làm với Node.js
của nhiều hoạt động với các lệnh gọi lại để tìm một thực thể mẹ, sau đó tìm các thực thể con thuộc về chính:
methodA(function(a){
methodB(function(b){
methodC(function(c){
methodD(function(d){
// Final callback code
})
})
})
})
Với async / await, các cuộc gọi của bạn sẽ được cấu trúc lại thành
router.post('/removeProduct', async (req, res) => {
try {
const product = await campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
{ new: true }
)
await campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } }
)
await campSchema.Campaign.remove({ "_id": { "$in": product.campaign } })
res.json(product)
} catch(err) {
throw err
}
})
Với mô-đun không đồng bộ, bạn có thể sử dụng phương thức chuỗi để giải quyết việc sử dụng lệnh gọi lại cho mã lồng nhau của nhiều phương thức có thể dẫn đến Địa ngục gọi lại :
Chuỗi :
async.series([
function(callback){
// code a
callback(null, 'a')
},
function(callback){
// code b
callback(null, 'b')
},
function(callback){
// code c
callback(null, 'c')
},
function(callback){
// code d
callback(null, 'd')
}],
// optional callback
function(err, results){
// results is ['a', 'b', 'c', 'd']
// final callback code
}
)
Hoặc thác nước :
async.waterfall([
function(callback){
// code a
callback(null, 'a', 'b')
},
function(arg1, arg2, callback){
// arg1 is equals 'a' and arg2 is 'b'
// Code c
callback(null, 'c')
},
function(arg1, callback){
// arg1 is 'c'
// code d
callback(null, 'd');
}], function (err, result) {
// result is 'd'
}
)
Bây giờ quay lại mã của bạn, sử dụng phương pháp thác nước không đồng bộ, sau đó, bạn có thể cấu trúc lại mã của mình thành
router.post('/removeProduct', function (req, res) {
async.waterfall([
function (callback) {
// code a: Remove Product
campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
function (err, product) {
if (err) callback(err);
callback(null, product);
}
);
},
function (doc, callback) {
// code b: Remove associated campaigns
var campaignList = doc.campaign;
campSchema.Campaign
.remove({ "_id": { "$in": campaignList } })
.exec(function (err, res) {
if (err) callback(err);
callback(null, doc);
}
);
},
function (doc, callback) {
// code c: Remove related partner
campSchema.Partner.update(
{ "products": doc._id },
{ "$pull": { "products": doc._id } },
function (err, res) {
if (err) callback(err);
callback(null, doc);
}
);
}
], function (err, result) {
if (err) throw err;
res.json(result); // OUTPUT OK
});
});