Node.js 在forEach循环中处理承诺

Node.js 在forEach循环中处理承诺,node.js,promise,aws-lambda,Node.js,Promise,Aws Lambda,我正在尝试运行一系列任务。每个任务都是动态的,可以遵循不同的规则。这将在AWS Lambda上执行 我有一个JSON数组。它有一个主体,其中包含任务名称,并且还具有属性 我需要动态加载一个javascript文件,文件名在正文中。 我需要等待,直到任务完成。或者它失败了(不管在哪里)。如果失败发生,我将需要在forEach循环中的当前记录中写入该数据 我有一个老问题,我的forEach首先完成,而不用等待任务完成。 这是forEach循环: const jobLoader = require('

我正在尝试运行一系列任务。每个任务都是动态的,可以遵循不同的规则。这将在AWS Lambda上执行

我有一个JSON数组。它有一个主体,其中包含任务名称,并且还具有属性

我需要动态加载一个javascript文件,文件名在正文中。 我需要等待,直到任务完成。或者它失败了(不管在哪里)。如果失败发生,我将需要在forEach循环中的当前记录中写入该数据

我有一个老问题,我的forEach首先完成,而不用等待任务完成。 这是forEach循环:

const jobLoader = require('./Helpers/jobLoader');

event.Records.forEach(record => {
    const { body: jobName } = record;
    const { messageAttributes } = record;

    const job = jobLoader.loadJob(jobName);

    job.runJob(messageAttributes).then(res => {
        console.log('Show results');
        return; // resume another record from forEach
    }).catch(err => {
         record.failed = true;
         record.failureMessage = err.message;
        console.log('I errored');
    });

    console.log('All Done');
});
问题是打印消息全部完成,然后打印消息显示结果。我从数据库中获取执行结果

这是加载任务的文件:

exports.loadJob = (jobName) => {
    const job = require(`../Tasks/${jobName}`);

    return job;
};
这是包含实际任务的文件: const mySqlConnector=require('../Storage/mySql')

这就是mySql连接器本身: const mysql=require('promise-mysql')

任务文件可以有任意数量的需要完成的内容,当我开始添加任务时,这些内容会有所不同。 我需要job.runJob完成,或者它捕获错误,无论它来自何处,所以我可以继续使用forEach

我尝试过使用map之类的工具,但最终的结果总是一样的


我做错了什么?

你可以使用
承诺。所有
方法:

const promises = event.Records.map(record => {
    const { body: jobName } = record;
    const { messageAttributes } = record;

    const job = jobLoader.loadJob(jobName);

    return job.runJob(messageAttributes).then(res => {
        console.log('Show results', res);
    }).catch(err => {
         record.failed = true;
         record.failureMessage = err.message;
        console.log('I errored');
        throw new Error('Your error !');
    });
});

try {
   const results = await Promise.all(promises);
   console.log('All done');
} catch (e) {
   console.log('Something has an error', e);
}

别忘了让你的函数异步

我设法解决了这个问题,但仍然保留了执行的细节:

大概是这样的:

for (let prop in event.Records){

        const { body: jobName } = event.Records[prop];
        const { messageAttributes } = event.Records[prop];

        const job = jobLoader.loadJob(jobName);

        await job.runJob(messageAttributes).then(res => {
            console.log('Show results', res);
        }).catch(err => {
            event.Records[prop].failed = true;
            event.Records[prop].failed = err.message;
            console.log('I errored');
        });

    }

我现在已经按预期的顺序工作了。但是数据库中的错误,由于某种原因,不会在catch块中传播。是的,这是因为你必须在catch块中抛出一个错误。对不起,我认为这是有意义的。但我永远不会在那个街区结束。我在mysql连接器中发现了错误,但它不会传播。在
处理程序中,您必须在catch语句中抛出错误。有没有一种方法可以做到这一点?原因是我丢失了事件出错的信息。最后,我希望有一个出错事件的列表,这样我就可以手动将它们发送到死SQS
const promises = event.Records.map(record => {
    const { body: jobName } = record;
    const { messageAttributes } = record;

    const job = jobLoader.loadJob(jobName);

    return job.runJob(messageAttributes).then(res => {
        console.log('Show results', res);
    }).catch(err => {
         record.failed = true;
         record.failureMessage = err.message;
        console.log('I errored');
        throw new Error('Your error !');
    });
});

try {
   const results = await Promise.all(promises);
   console.log('All done');
} catch (e) {
   console.log('Something has an error', e);
}
for (let prop in event.Records){

        const { body: jobName } = event.Records[prop];
        const { messageAttributes } = event.Records[prop];

        const job = jobLoader.loadJob(jobName);

        await job.runJob(messageAttributes).then(res => {
            console.log('Show results', res);
        }).catch(err => {
            event.Records[prop].failed = true;
            event.Records[prop].failed = err.message;
            console.log('I errored');
        });

    }