最近AWS宣布了其lambda函数(Node.js 8.10 runtime available)的nodejs8.10运行时的可用性。虽然这对于快乐的流程来说似乎很好,但是我遇到了一些不愉快的流程问题,即我得到了“UnhandledPromiseRejectionWarnings”。
我正在使用以下代码。我的想法是,我提供了一个不存在的对象的密钥来测试该场景的不满意流程。我的目标是将错误记录并传播出lambda,因为我在这里没有理智的处理方式(我无法在这个lambda函数中检索新密钥)。我也希望能够在调用者中使用错误(例如,另一个lambda函数或步骤函数)。
'use strict';
const AWS = require('aws-sdk');
exports.handler = async (event) => {
let data;
try {
data = await getObject(event.key);
} catch (err) {
console.error('So this happened:', err);
throw err;
}
return data;
}
const getObject = async (key) => {
let params = {
Bucket: process.env.BUCKET,
Key: key
};
const s3 = new AWS.S3();
let data;
try {
data = await s3.getObject(params).promise();
} catch(err) {
console.log('Error retrieving object');
throw err;
}
console.log('Retrieved data');
return data.Body.toString('utf8');
}
如果我运行这个lambda函数(使用SAM local),我会像我想的那样从lambda中得到错误,但我也收到以下警告:
2018-04-18T07:54:16.217Z 6ecc84eb-46f6-1b08-23fb-46de7c5ba6eb (node:1) UnhandledPromiseRejectionWarning: NoSuchKey: The specified key does not exist.
at Request.extractError (/var/task/node_modules/aws-sdk/lib/services/s3.js:577:35)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
2018-04-18T07:54:16.218Z 6ecc84eb-46f6-1b08-23fb-46de7c5ba6eb (node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
2018-04-18T07:54:16.218Z 6ecc84eb-46f6-1b08-23fb-46de7c5ba6eb (node:1) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
我不确定如何处理这个问题,同时仍然将错误传播出lambda函数(根据lambda function errors (node.js)应该是一个有效的场景)
我也尝试过运行类似(对我而言)的场景,如下面的那样(尝试查明并理解错误),但不知怎的,我在这里得不到警告,它按预期工作(错误返回来自lambda函数)。
'use strict';
const AWS = require('aws-sdk');
exports.handler = async (event) => {
let data;
try {
data = await directBoom();
} catch (err) {
console.error('So this happened:', err);
throw err;
}
return data;
}
const directBoom = async () => {
let data;
try {
data = await Promise.reject(new Error('boom!'));
} catch(err) {
throw err;
}
return data;
}
我在这里缺少什么,为什么两个例子表现不同?如何在第一个示例中摆脱警告,同时仍然能够将错误传播出lambda函数?任何帮助将不胜感激。
答案 0 :(得分:5)
任何时候在promise / async函数中抛出或拒绝并且不使用catch处理它,Node将返回该警告。
AWS上的example不会在catch块中抛出错误,而是返回它:
let AWS = require('aws-sdk');
let lambda = new AWS.Lambda();
let data;
exports.handler = async (event) => {
try {
data = await lambda.getAccountSettings().promise();
}
catch (err) {
console.log(err);
return err;
}
return data;
};
在具有大量异步函数的大型应用程序中,如果单个未处理的承诺终止,那么节点进程就会很糟糕。这可能不适用于简单的Lambda函数,其中抛出终止进程的错误是期望的行为。但是,如果您不希望Node警告您,请返回错误。
答案 1 :(得分:2)
AWS似乎已解决此问题。使用Node 8.10运行时使用以下功能进行测试,我再也看不到任何未处理的拒绝:
exports.handler = async (event) => {
throw new Error("broken")
};
答案 2 :(得分:0)
我通过使用上下文对象中的fail
方法来通知Lambda函数执行失败,来对此进行管理。
'use strict'
exports.handler = async function (event, context) {
try {
throw new Error('Something went wrong')
} catch (err) {
context.fail(err)
}
}