forEach не работает внутри лямбда-функции - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть Node.js AWS функция Lamba, которая выполняет вызов БД, затем принимает и разбивает результаты вызова БД на различные сообщения SQS. В настоящее время кажется, что это не работает, поскольку Lambda пропускает все, и когда я добавляю await (как показано ниже), он говорит мне, что я не могу использовать await для части sendMessage.

module.exports.companyID = async (event, context, callback) => {
    context.callbackWaitsForEmptyEventLoop = false;
    if (inter_conn == null) {
        inter_conn = await mongoose.createConnection(incident_Mongo_URI, {
            bufferCommands: false, // Disable mongoose buffering
            bufferMaxEntries: 0, // and MongoDB driver buffering
            useNewUrlParser: true // Required or it gives me an error
        });
    }

    const I = inter_conn.model('Incident');
    await I.find().distinct('companyID').exec(function(err, results) {
        if(err) {
            logger.error(`Inter Cleanup: Find: Error message: ${JSON.stringify(err)}`);
            process.exit(1);
        }
        logger.info(results)
        results.forEach(companyID => {
            let params = {
                MessageBody: companyID,
                QueueUrl: process.env.incidentsQueue,
                DelaySeconds: 0
            };

            let sendMessage = sqs.sendMessage(params).promise();

            await sendMessage.then((data) => {
                logger.info(data)
            })
            .catch((err) => {
                logger.error(err)
            })
        }); 
    })

    let output = {
        status: 'Done'
    }
    callback(null, output);
};

Сообщение об ошибке как видно из консоли Lambda

{
  "errorType": "Runtime.UserCodeSyntaxError",
  "errorMessage": "SyntaxError: await is only valid in async function",
  "trace": [
    "Runtime.UserCodeSyntaxError: SyntaxError: await is only valid in async function",
    "    at _loadUserApp (/var/runtime/UserFunction.js:98:13)",
    "    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
    "    at Object.<anonymous> (/var/runtime/index.js:45:30)",
    "    at Module._compile (internal/modules/cjs/loader.js:778:30)",
    "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)",
    "    at Module.load (internal/modules/cjs/loader.js:653:32)",
    "    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)",
    "    at Function.Module._load (internal/modules/cjs/loader.js:585:3)",
    "    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)",
    "    at startup (internal/bootstrap/node.js:283:19)"
  ]
}

Я проверил базовый код без лямбда-кода, и async / await в файле JS работал как скрипт, и он работал нормально.

Я знаю, что проблема заключается в преобразовании этого значения в лямбду и связано с тем, что лямбда является асинхронной / ожидающей.

Как я могу сделать так, чтобы моя Lambda вызывала базу данных и запускала forEach, помещая каждый элемент в массиве результатов в сообщение SQS?

1 Ответ

1 голос
/ 13 февраля 2020

Ошибка, которую вы получаете, заключается в том, что вы пытаетесь await внутри вашего forEach, который не async. Не думайте, однако, что вы можете просто сделать эту функцию async тоже.

Лучшее решение - прекратить использование .forEach и использовать более современный for/of. Ваш запрос для l oop будет выглядеть примерно так:

        for (let companyID of results) {
            let params = {
                MessageBody: companyID,
                QueueUrl: process.env.incidentsQueue,
                DelaySeconds: 0
            };

            try {
                const data = await sqs.sendMessage(params).promise();

                logger.info(data)
            }
            catch (err) {
                logger.error(err);
            }
        }

ПРИМЕЧАНИЕ , я также изменил вызов sendMessage, чтобы использовать подходящее ожидание.

...