Ще трябва да вложите обажданията си, за да премахнете идентификатора на продукта от другия модел. Например във вашето обаждане за премахване на продукта от Продукт
колекция, можете също да направите друго обаждане, за да премахнете референтния файл от Партньора
модел в рамките на обратното извикване на резултатите. Премахването на продукта по подразбиране ще премахне неговите препратки към Кампания
Модел.
Следният код показва горната интуиция:
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);
}
);
});
});
За да премахнете свързаните кампании, тогава може да се нуждаете от допълнителна операция за премахване, която взема идентификатора на свързаната кампания от даден идентификатор на продукт. Помислете за следния мръсен хак, който потенциално може да ви осигури еднопосочен билет до callback hell ако не внимавате с влагането на обратното извикване:
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);
})
}
);
}
);
});
Въпреки че работи, горният потенциален капан може да бъде избегнат чрез използване на async/await или async
библиотека. Но първо, за да ви дам по-добро разбиране на използването на множество обратни извиквания с asyncкод>
модул, нека илюстрираме това с пример от Seven Неща, които трябва да спрете да правите с Node.js
на множество операции с обратни извиквания за намиране на родителски обект, след което намиране на дъщерни обекти, които принадлежат на родителя:
methodA(function(a){
methodB(function(b){
methodC(function(c){
methodD(function(d){
// Final callback code
})
})
})
})
С async/await вашите повиквания ще бъдат преструктурирани, структурирани като
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
}
})
С модула async можете или да използвате метода series за справяне с използването на обратни извиквания за код за влагане на множество методи, което може да доведе до Адът за обратно извикване :
Поредица :
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
}
)
Или водопад :
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'
}
)
Сега се връщаме към кода ви, използвайки метода на асинхронен каскад, след което можете да преструктурирате кода си до
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
});
});