我知道这对人们来说是一个普遍的问题,我已经查看了一些指南并查看了文档,但是我不了解正在发生的事情,并且希望获得一些帮助。
这是我正在使用的控制器功能:
exports.appDetail = function (req, res) {
appRepo.findWithId(req.params.id, (err, myApp) => {
if (err) {
console.log(err)
}
getDeviceData(myApp.devices, (err, myDeviceData) => {
if (err) console.log(err)
console.log(JSON.stringify(myDeviceData) + ' || myDeviceData')
// construct object to be returned
let appsDataObject = {
name: myApp.name,
user_id: myApp.user_id,
devices: myDeviceData,
permissions: myApp.permissions
}
return res.status(200).send(appsDataObject)
})
})
}
// write async function here
const getDeviceData = function (devices, callback) {
let devicesDataArray = []
async.each(devices, function (device, cb) {
deviceRepo.findById(new ObjectID(device), (err, myDevice) => {
if (err) {
cb(err)
}
// get device data, push to devices array
let deviceObj = {
name: myDevice.name,
version: myDevice.version
}
devicesDataArray.push(deviceObj)
console.log(JSON.stringify(devicesDataArray) + ' || devicesDataAray after obj push')
})
cb(null, devicesDataArray)
}, function (err) {
// if any of the file processing produced an error, err would equal that error
if (err) console.log(err)
})
callback(null, devicesDataArray)
}
我最初是用for循环和回调编写的,但是我认为这样做是不可能的(尽管我不确定)。如果有更好的方法来进行异步循环,请告诉我。
第8行上有一条日志语句myDeviceData
。这应该通过回调返回我想要的数据,但是此日志语句始终返回为空。而且由于其他日志语句表明数据格式正确,所以问题一定出在通过getDeviceData()
的回调返回我需要的数据。大概callback(null, devicesDataArray)
应该这样做。
很明显,我不理解这些异步功能应该如何工作。有人可以帮我了解如何从这些async.each函数中获取值吗?谢谢。
编辑:
我对代码进行了重构,以使其更清晰,更好地解决问题,并且我查明了问题出在哪里。在此函数的开头,我将devicesDataArray
定义为一个空数组,最后,我返回了该数组。里面的所有事情都应该发生,但是我不知道如何告诉返回要等到数组不为空时,如果有意义,这是新代码:
let getData = async function (devices) {
let devicesDataArray = []
for (let i = 0; i < devices.length; i++) {
deviceRepo.findById(new ObjectID(devices[i]), async (err, myDevice) => {
if (err) {
console.log(err)
}
console.log(JSON.stringify(myDevice) + ' || myDevice')
let deviceObj = await {
name: myDevice.name,
version: myDevice.version
}
console.log(JSON.stringify(deviceObj) + ' || deviceObj')
await devicesDataArray.push(deviceObj)
console.log(JSON.stringify(devicesDataArray) + ' || devicesDataArray after push')
})
}
console.log(JSON.stringify(devicesDataArray) + ' || devicesDataArray before return')
return Promise.all(devicesDataArray) // problem is here.
}
感谢您提供任何有助于理解这一点的帮助。
答案 0 :(得分:0)
我们在这里使用Promise
Promise
对象将立即返回,我们在其中执行异步代码。
const someFuncThatTakesTime = () => {
// Here is our ASYNC
return new Promise((resolve, reject) => {
// In here we are synchronous again.
const myArray = [];
for(x = 0; x < 10; x++) {
myArray.push(x);
}
// Here is the callback
setTimeout(() => resolve(myArray), 3000);
});
};
someFuncThatTakesTime().then(array => console.log(array));
答案 1 :(得分:0)
首先,我宁愿避免使用回调,因为它会使您的代码不可读,
您也可以使用javascript方法处理async
,而无需使用其他模块。
问题的原因在于您执行了async.each函数,而无需等待它的内部内容
并且您这里有deviceRepo.findById
是异步功能,需要等待
我使用异步等待重构了您的代码,希望这可以简化问题
exports.appDetail = function async(req, res) {
try {
const myApp = await appRepo.findWithId(req.params.id)
const myDeviceData = await getDeviceData(myApp.device)
console.log(JSON.stringify(myDeviceData) + ' || myDeviceData')
// construct object to be returned
let appsDataObject = {
name: myApp.name,
user_id: myApp.user_id,
devices: myDeviceData,
permissions: myApp.permissions
}
return res.status(200).send(appsDataObject)
} catch (err) {
console.log(err)
}
}
// write async function here
const getDeviceData = function async(devices) {
let devicesDataArrayPromises = devices.map(async(device)=>{
const myDevice= await deviceRepo.findById(new ObjectID(device))
let deviceObj = {
name: myDevice.name,
version: myDevice.version
}
return deviceObj
})
const devicesDataArray = await Promise.all(devicesDataArrayPromises)
console.log(JSON.stringify(devicesDataArray) + ' || devicesDataAray after obj push')
return devicesDataArray
}