带有异步库的循环内的 Mongoose 异步调用
Mongoose async call inside a loop with async library
我刚开始使用 nodejs/mongoose,我想我有一个典型的异步问题。有人可以指导我如何解决这个异步问题吗?
我有这个函数 "getAreasRoot" 并且在里面我有一个循环来用另一个异步函数的结果填充子项。如何使用异步库修复它?
areaSchema.statics.getAreasRoot = function(cb: any) {
let self = this;
return self.model("Area").find({ parentId: null }, function(err: any, docs: any){
docs.forEach(function(doc: any){
doc.name = "Hi " + doc.name;
doc.children = self.model("Area").getAreasChildren(doc._id, function(err: any, docs: any){});
})
cb(err, docs);
});
};
areaSchema.statics.getAreasChildren = function(id: any, cb: any) {
return this.model("Area").find({ parentId: null }).exec(cb);
}
您有 2 个任务:获取根,然后使用根获取 children。
如果我要使用 async.js 来执行此操作,我会使用 async.waterfall and async.mapSeries 的组合。我们使用 .waterfall
是因为我们想将第一个任务的结果传递给第二个任务。我们使用 .mapSeries
是因为我们想改变每个根区域的名称和 children.
areaSchema.statics.getAreasRoot = function (cb) {
let self = this;
async.waterfall([
// every task has a callback that must be fired at least/most once
// to tell that the task has finished OR when an error has occurred
function getRoots (cb1) {
self.find({ parentId: null }, cb1);
},
function getChildren (roots, cb2) {
async.mapSeries(roots, function (root, cb3) {
// inside this block, we want to fire the innest callback cb3 when
// each iteration is done OR when an error occurs to stop .mapSeries
self.find({ parentId: root._id }, function (err, children) {
// error: stop .mapSeries
if (err)
return cb3(err);
root.name = "Hi " + root.name;
root.children = children;
// done: send back the altered document
cb3(null, root);
});
// the last argument is fired when .mapSeries has finished its iterations
// OR when an error has occurred; we simply pass the inner callback cb2
}, cb2)
}
// the last argument is fired when .waterfall has finished its tasks
// OR when an error has occurred; we simply pass the original callback cb
], cb);
};
使用它
Area.getAreasRoot(function (err, areas) {
console.log(err, areas);
})
一边
Mongoose 操作是异步的,所以
doc.children = self.model("Area").getAreasChildren(...)
不正确,因为您返回的 Promise 与实际文档相反。
还有
您可能能够使用virtual population or aggregation简化您的逻辑。
我刚开始使用 nodejs/mongoose,我想我有一个典型的异步问题。有人可以指导我如何解决这个异步问题吗?
我有这个函数 "getAreasRoot" 并且在里面我有一个循环来用另一个异步函数的结果填充子项。如何使用异步库修复它?
areaSchema.statics.getAreasRoot = function(cb: any) {
let self = this;
return self.model("Area").find({ parentId: null }, function(err: any, docs: any){
docs.forEach(function(doc: any){
doc.name = "Hi " + doc.name;
doc.children = self.model("Area").getAreasChildren(doc._id, function(err: any, docs: any){});
})
cb(err, docs);
});
};
areaSchema.statics.getAreasChildren = function(id: any, cb: any) {
return this.model("Area").find({ parentId: null }).exec(cb);
}
您有 2 个任务:获取根,然后使用根获取 children。
如果我要使用 async.js 来执行此操作,我会使用 async.waterfall and async.mapSeries 的组合。我们使用 .waterfall
是因为我们想将第一个任务的结果传递给第二个任务。我们使用 .mapSeries
是因为我们想改变每个根区域的名称和 children.
areaSchema.statics.getAreasRoot = function (cb) {
let self = this;
async.waterfall([
// every task has a callback that must be fired at least/most once
// to tell that the task has finished OR when an error has occurred
function getRoots (cb1) {
self.find({ parentId: null }, cb1);
},
function getChildren (roots, cb2) {
async.mapSeries(roots, function (root, cb3) {
// inside this block, we want to fire the innest callback cb3 when
// each iteration is done OR when an error occurs to stop .mapSeries
self.find({ parentId: root._id }, function (err, children) {
// error: stop .mapSeries
if (err)
return cb3(err);
root.name = "Hi " + root.name;
root.children = children;
// done: send back the altered document
cb3(null, root);
});
// the last argument is fired when .mapSeries has finished its iterations
// OR when an error has occurred; we simply pass the inner callback cb2
}, cb2)
}
// the last argument is fired when .waterfall has finished its tasks
// OR when an error has occurred; we simply pass the original callback cb
], cb);
};
使用它
Area.getAreasRoot(function (err, areas) {
console.log(err, areas);
})
一边
Mongoose 操作是异步的,所以
doc.children = self.model("Area").getAreasChildren(...)
不正确,因为您返回的 Promise 与实际文档相反。
还有
您可能能够使用virtual population or aggregation简化您的逻辑。