node.js – 使用async/await的AWS lambda上的未处理承诺拒绝

最近,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函数?任何帮助,将不胜感激.

最佳答案
每当你在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警告您,请返回错误.

转载注明原文:node.js – 使用async/await的AWS lambda上的未处理承诺拒绝 - 代码日志