【问题标题】:Handling promises inside the forEach loop在 forEach 循环中处理 Promise
【发布时间】:2019-02-14 22:39:31
【问题描述】:

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

我有一个 JSON 数组。它有一个body,里面有任务名称,它也有属性。

我需要在 body 中动态加载一个带有名称的 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');
});

问题是消息 All Done 被打印,然后消息 show results 被打印。一旦执行,我就会从数据库中获取结果。

这是加载任务的文件:

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

    return job;
};

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

exports.runJob = async (params) => {
  let payload = {};

    let dataToSend = await getUserName(params.userId.stringValue);

    payload.dataToSend = dataToSend;

    let moreDataToSend = await getEvenMoreData(params.userId.stringValue);

    payload.moreDataToSend = moreDataToSend;

    return await sendData(payload);
};

const getUserName = async (userId) => {
    const query = 'SELECT * FROM user_data';
    return await mySqlConnector.handler(query);
};

const getEvenMoreData = async (userId) => {
    const query = 'SELECT * FROM user_data';
    return await mySqlConnector.handler(query);
};


const sendData = (payload) => {

  //this should be Axios sending data
};

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

exports.handler = async (query) => {
   return mysql.createConnection({
        host     : '127.0.0.1',
        user     : 'root',
        password : '',
        database: 'crm'
    }).then(conn =>{
        let result = conn.query(query);
        conn.end();
        return result;
    }).then(rows => {
        //console.log("These are rows:" + rows);
        return rows;
    }).catch(error => {
        return error;
    });
};

任务文件可以有任意数量的需要完成的事情,当我开始添加任务时会有所不同。 我需要 job.runJob 从它起源的任何位置完成,或者它捕获一个错误,这样我就可以继续使用 forEach。

我已经尝试过使用 map 什么的,但最终的结果总是一样的。

我做错了什么?

【问题讨论】:

    标签: node.js promise aws-lambda


    【解决方案1】:

    你可以使用Promise.all方法:

    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);
    }
    

    别忘了让你的函数异步!

    【讨论】:

    • 我现在让它按预期的顺序工作。但是由于某种原因,来自数据库的错误不会在 catch 块中传播。
    • 是的,这是因为你必须在 catch 块中抛出一个错误对不起我编辑
    • 这是有道理的。但我从来没有在那个街区结束。我在 mysql 连接器中有错误,但它没有传播。
    • 在您的 handler 函数中,您必须在 catch 语句中抛出错误
    • 没有 Promise.all 有没有办法做到这一点?原因是我丢失了错误事件的信息。最后我想要一个错误事件的列表,所以我可以手动将它们发送到 Dead SQS
    【解决方案2】:

    我设法解决了它,并且仍然保留有关执行的详细信息:

    类似这样的:

    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');
            });
    
        }
    

    【讨论】:

      猜你喜欢
      • 2021-07-14
      • 2018-02-12
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 2020-11-13
      • 2021-01-19
      • 2019-05-22
      相关资源
      最近更新 更多