Работа с вложенным forEach в Node.js - PullRequest
0 голосов
/ 25 мая 2020

Я работаю над чем-то, что требует вложенных циклов foreach для обработки некоторых данных.

Имеется в виду массив идентификаторов, которые мне нужно найти, каждый идентификатор, связанный с пользователем, и мне просто нужно извлечь их имена из ответа на вызов API. Служба A имеет список идентификаторов и затем отправляет 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 из этого сообщения в блоге, что позволило мне сделать еще один раньше, хотя этот не будет работать

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

редактировать переменные показа

let foo let foobarArray = []

Добавлено ожидание в пользовательский контроллер, теперь он получает правильный вывод, но сообщение об ошибке говорит Cannot set headers after they are sent to the client

Имена приходят извне кода и просто нужны там, где они есть. Не знаю, как объяснить это, не объясняя проект полностью / подробно.

редактировать код показа для 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)
        })
    })
}

Этот код работает отлично, как ожидалось - ie он отправляет запрос с правильной полезной нагрузкой и возвращает правильный ответ.

Попытка редактирования текущего кода

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

SyntaxError: await is only valid in async function

попытка редактирования при выполнении функции asyn c (обычно я не 'не используйте async / await вместо использования обещаний)

Даже после кода попытки ниже он все еще дает сообщение об ошибке выше - я пробовал тот же код, прежде чем редактировать, чтобы показать сообщение об ошибке

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 - это массив имен собственных, а не идентификаторов. Собственные имена выбираются через userController.userInfo, куда передается идентификатор.

edit - Новый код после asyn c и 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

Похоже, функция должна быть асинхронной c уже (поместите asyn c перед function name).

1 Ответ

1 голос
/ 26 мая 2020

Думаю, вы ищете простой

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: []})
    }    
}
...