AWS SQS Node.js 脚本不等待

AWS SQS Node.js script does not await

正在尝试发送多条消息(来自 AWS SQS lambda,如果这很重要)但它永远不会等待承诺。

function getEndpoint(settings){
    return new Promise(function(resolve, reject) { 
    // [...] more stuff here
}

然后循环调用:

exports.handler = async (event) => {
    var messages = [];
    event.Records.forEach(function(messageId, body) {
        //options object created from some stuff
        messages.push(getEndpoint(options).then(function(response){
            console.log("anything at all"); //NEVER LOGGED
        }));
    });
    await Promise.all(messages);
};

但是等待似乎被完全跳过了。我不确定如何使用显式 await 获得 Process exited before completing request。我在其他有效的脚本中有类似的 async await/promise 设置,但无法发现我在这个脚本中做错了什么。

你忘了 return lambda:

exports.handler = async (event) => {
    var messages = [];
    event.Records.forEach(function(messageId, body) {
        //options object created from some stuff
        messages.push(getEndpoint(options));
    });
    await Promise.all(messages);
    return 'OK'
};

这也应该有效:

exports.handler = (event) => { // async is not mandatory here
    var messages = [];
    event.Records.forEach(function(messageId, body) {
        //options object created from some stuff
        messages.push(getEndpoint(options));
    });
    return Promise.all(messages); // returning a promise
};

你可以使用地图:

exports.handler = (event) => { // async is not mandatory here
    const messages = event.Records.map(function(messageId, body) {
        //options object created from some stuff
        return getEndpoint(options)
    });
    return Promise.all(messages); // returning a promise
};

要理解为什么会发生这种情况,您必须深入研究 lambda 的实现:它基本上会等待函数堆栈被清除,并且由于您根本没有 return 任何东西,函数堆栈在将所有东西排队后立即变空 - 在 await 调用后添加一个简单的 return 使 fn 堆栈不为空,这意味着 lambda 将等待它完成。

如果你在标准节点上 运行 这个,你的函数也会 return 在承诺完成之前但是你的节点进程不会退出,直到堆栈被清除。这是 lambda 与 stock 节点不同的地方。