我在另一个mongoose查询中调用mongoose查询。当我将结果推送到数组时,我最后检查它是否为空。经过大量的搜索后,发现问题是这是异步执行的。但无法找到如何解决问题。我的代码如下。
Bus.find().exec(function(err,buses) {
if(err)
console.log(err);
if (buses[0] != null){
const cords = [];
buses.forEach( function (bus) {
// console.log(bus);
Position.findOne({"busId": bus.busId},{}, {sort : {'time' : -1}}, function (err, position) {
cords.push(position);
console.log(cords);
// console.log(position);
});
console.log(cords);
},
function (err) {
if (err){
console.log(err,"Errrrrrrrrrrrrr");
}
});
console.log(cords);
res.json({cords: cords});
}
答案 0 :(得分:2)
嗯,您的代码存在许多问题,但其中最主要的一点是,您无法保存或处理回调内部回调之外的任何值。你的例子(为了清楚起见重写):
var result = []
arry.forEach(function(opt) {
async.call(args, function(err,value) {
result.push(value)
})
})
// result is empty here!
由于您无法知道内部回调何时完成,因此无法正常工作。
根据定义,回调将在未来的某个时间触发,并且由于您无法知道何时,您必须使用传递给回调的结果进行所有计算 在回调本身!
否则会给你不一致的结果。
(注意:乘坐火车时在iPad上匆匆键入,如果需要,将在稍后修复。)
最好的方法是使用Promises来聚合结果。这是一个天真的例子:
/*
* given a value and an optional array (accum),
* pass the value to the async func and add its result to accum
* if accum is not an array, make it one
* return accum
*/
var do_something = (value, accum) => {
// on first pass, accum will be undefined, so make it an array
accum = Array.isArray(accum) ? accum : []
return new Promise((resolve, reject) => {
async_func(value, (err, res) => {
if(err) {
reject(err)
}
accum.append(res)
resolve(accum)
})
})
}
/*
* for each member of input array, apply do_something
* then operate on accumulated result.
*/
Promise.map(input, do_something)
.then(results => {
// results will contain the accumulated results from all
// the mapped operations
})
.catch(err => {
throw err
})
仅使用回调,您可以使用以下方法获得相同的结果:
const inputs = [...] // array of inputs to pass to async function
const expected_num_of_results = inputs.length
let results = []
const onComplete = (results) => {
// do something with completed results here
console.log(`results: ${results}`);
}
const onResult = (err, res) => { // callback to async_func
if(err) {
throw new Error(`on iteration ${results.length+1}: ${err}`)
}
results.push(res) // save result to accumulator
if( results.length >= expected_num_of_results) { // are we done?
onComplete(results) // process results
}
}
// example async func - REPLACE with actual async function
const async_func = (val,cb) => {
// call callback with no error and supplied value multiplied by 2
cb(null,val*2)
}
// wrapper that takes one value
// and calls async_func with it and predefined callback
const do_async = (value) => {
async_func(value, onResult)
}
// process inputs
inputs.forEach(do_async)
所以:
const inputs = [1,2,3,4,5]
将打印:
results: 2,4,6,8,10