处理 Node.js 中的嵌套 forEach

Dealing with nested forEach in Node.js

我正在做一些需要嵌套 foreach 循环来处理一些数据的事情。

目的是我需要查找一个 ID 数组,每个 ID 都与一个用户相关,我只需要从 API 调用的响应中提取他们的名字。服务 A 有 ID 列表,然后针对每个 ID 向服务 B 发送一个 HTTP GET 请求(无法更改),然后服务 B 以

的格式响应正确的信息
{
  success: true,
  user: {
    name: 'John Doe'
  }
}

无效但我当前使用的代码

incidents.forEach((name) => {
    foo = {
        nameID: names 
    }
    const asyncForEach = async (array, callback) => {
        for(let index = 0; index < array.length; index++) {
            await callback(array[index], index, array)
        }
    }
    const startMulti = async () => {
    await asyncForEach(foo.nameID, async (obj, index) => {
        await userController.userInfo(obj)
            .then((userInfo) => {
                foo.nameID[index] = userInfo.user.name
            })
            .then(() => {
                foobarArray.push(foo)
            })
        })
        return res.json({success: true, foobar: foobarArray})
    }
    startMulti()

})

从这个博客中获得了嵌套 foreach 循环的原始想法 post 这让我之前可以做另一个,尽管这个不起作用

https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404

编辑显示变量

让 foo 让 foobarArray = []

添加等待到用户控制器现在得到正确的输出但错误消息说 Cannot set headers after they are sent to the client

名称来自代码外部,只需要它所在的地方。不知道如何在不解释 whole/detail.

中的项目的情况下解释它

编辑 usercontroller.userinfo

的显示代码
exports.userInfo = function(id) {
    return new Promise((resolve, reject) => {
        let user = {
            _id: id
        }
        options.json = {user}
        request.get('/userInfo', options, (err, response, body) => {
            resolve(body)
        })
    })
}

此代码按预期完美工作 - 即它发送带有正确负载的请求和 returns 正确响应。

编辑当前代码尝试

let foobarArray =[]
let names = []
let foo
for (const incident of incidents) {
    foo = {
        nameID: names
    }
    for (const id of incident.names) {
        const userInfo = await userController.userInfo(id)
        names.push(userInfo.user.name)

    }
}
return res.json({success: true, fooreturned: foobarArray})

userController前面await导致的错误信息

SyntaxError: await is only valid in async function

编辑制作异步函数的尝试(我通常不使用 async/await 而是使用 promises)

即使在尝试下面的代码之后它仍然会给出上面的错误消息 - 我在编辑以显示错误消息之前尝试过相同的代码

exports.userInfo = async function(id) {
    return new Promise((resolve, reject) => {
        let user = {
            _id: id
        }
        options.json = {user}
        request.get('/userInfo', options, (err, response, body) => {
            resolve(body)
        })
    })
}

下面的完整代码,上面已经显示的 userInfo 函数除外。

exports.monitor = function(req, res, next) {
    const fooID = req.params.id
    let foobarArray =[]
    let names = []
    let foo
    Incident.find({fooID})
    .exec((err, incidents) => {
        if(err) {
            console.log(err)
            return res.json({success: false, foobar: []})
        }
        if(incidents != []) {           
            for (const incident of incidents) {
                foo = {
                    nameID: incident.foo[0].names
                }
                for (const id of foo.responded) {
                    const userInfo = await userController.userInfo(id)
                    names.push(userInfo.user.name)

                }
            }
            return res.json({success: true, foobar: foobarArray})
        }

    })
}

除了我还需要添加的一些日志记录行之外,这几乎就是全部代码了。我非常需要 foobar: foobarArray 成为一个对象数组 - foo - 其中 nameID 是专有名称而不是 ID 的数组。通过传递 ID 的 userController.userInfo 获取专有名称。

编辑 - 异步和 promisify 之后的新代码 - 不确定我是否正确执行了 promisify

exports.monitor = async function(req, res, next) {
    const fooID = req.params.id
    const incidents = await userController.incidentFind(fooID)

}

exports.incidentFind = async function(id) {
    return new Promise((resolve, reject) => {
        const sevenAgo = moment().subtract(7, 'days').toISOString()
        let alertArray =[]
        let names = []
        let alert
        Incident.find({monitorID, createdAt: {$gte: sevenAgo}})
        .exec((err, incidents) => {
        if(err) {
            console.log(err)
            return res.json({success: false, foobar: []})
        }
        if(incidents != []) {           
            for (const incident of incidents) {
                foo = {
                    nameID: incident.foo[0].names
                }
                for (const id of foo.responded) {
                    const userInfo = await userController.userInfo(id)
                    names.push(userInfo.user.name)

                }
            }
            return res.json({success: true, foobar: foobarArray})
        }

        })
    })
}

不确定实际控制人monitor应该包含什么内容。有点丢失

错误信息

/home/me/Projects/app/incidents/controllers/users.js:100
const userInfo = await userController.userInfo(id)
                 ^^^^^

SyntaxError: await is only valid in async function

看起来该函数应该已经是异步的(将异步放在 function 名称之前)。

我认为你正在寻找一个简单的

exports.monitor = async function(req, res, next) {
    const fooID = req.params.id
    const foobarArray = […]
    const names = […]
    try {
        const incidents = await Incident.find({fooID}).exec()
        for (const name of incidents) {
            const foo = {
                nameID: []
            }
            for (const userId of names) {
                const userInfo = await userController.userInfo(userId)
                foo.nameID.push(userInfo.user.name)
            }
            foobarArray.push(foo)
        }
        res.json({success: true, foobar: foobarArray})
    } catch(err) {
        console.log(err)
        res.json({success: false, foobar: []})
    }    
}