Du skal indlejre dine opkald for at fjerne produkt-id'et fra den anden model. For eksempel i dit opkald om at fjerne produktet fra Produkt
indsamling, kan du også foretage et andet opkald for at fjerne referenten fra Partner
model inden for resultaterne tilbagekald. Fjernelse af produktet som standard vil fjerne dets referencer til Kampagnen
Model.
Følgende kode viser intuitionen ovenfor:
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);
}
);
});
});
For at fjerne de tilknyttede kampagner, skal du muligvis have en ekstra fjernoperation, der tager det tilknyttede kampagne-id fra et givet produkt-id. Overvej følgende beskidte hack, som potentielt kan give dig en enkeltbillet til callbackhell hvis du ikke er forsigtig med tilbagekaldsindlejringen:
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);
})
}
);
}
);
});
Selvom det virker, kan ovenstående potentielle faldgrube undgås ved at bruge async/await eller async
bibliotek. Men for det første for at give dig en bedre forståelse af brugen af flere tilbagekald med async
modul, lad os illustrere dette med et eksempel fra Seven Ting du bør stoppe med at gøre med Node.js
af flere operationer med tilbagekald for at finde en overordnet enhed, og find derefter underordnede enheder, der tilhører overordnet:
methodA(function(a){
methodB(function(b){
methodC(function(c){
methodD(function(d){
// Final callback code
})
})
})
})
Med async/wait vil dine opkald blive omstruktureret struktureret som
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
}
})
Med async-modulet kan du enten bruge seriemetoden til at adressere brugen af tilbagekald til indlejringskode for flere metoder, hvilket kan resultere i Callback Hell :
Serie :
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
}
)
Eller vandfaldet :
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'
}
)
Går nu tilbage til din kode, ved at bruge den asynkrone vandfaldsmetode, kan du derefter omstrukturere din kode til
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
});
});