阅读背景:

使用async / await对AWS lambda上的未处理承诺拒绝

来源:互联网 

Recently AWS announced the availability of the nodejs8.10 runtime for their lambda functions (Node.js 8.10 runtime available). While this seemed great for the happy flow, I'm running into some problems with the unhappy flow, i.e. I'm getting 'UnhandledPromiseRejectionWarnings'.

最近,AWS宣布了其lambda函数(Node.js 8.10运行时可用)的nodejs8.10运行时的可用性。虽然这对于快乐的流程来说似乎很好,但我遇到了一些不愉快的流程问题,即我得到了“UnhandledPromiseRejectionWarnings”。

I'm using the below code. The idea is that I provide a key to a non-existent object to test out the unhappy flow for that scenario. My goal is for the error to get logged and propagated out of the lambda since I have no sane way of handling it here (I have no way to retrieve a new key within this lambda function). I also would like to be able to use the error in the caller (e.g. another lambda function or step functions).

我正在使用以下代码。我的想法是,我提供了一个不存在的对象的密钥来测试该场景的不满意流程。我的目标是将错误记录并传播出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');
}

If I run this lambda function (with SAM local) I get the error back out of the lambda like I want, but I also get the following warning(s):

如果我运行这个lambda函数(使用SAM本地),我会像我想的那样从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.

I'm not sure how to handle this while still propagating the error out of the lambda function (which should be a valid scenario according to lambda function errors (node.js))

我还不确定如何处理这个问题,同时仍然将错误传播出lambda函数(根据lambda函数错误(node.js)应该是一个有效的场景)

I've also tried running a similar (to me) scenario like the one below (to try and pinpoint and understand the error) but somehow here I do not get the warning and it is working as intended (the error is returned from the lambda function).

我也试过运行一个类似(对我来说)场景,如下面的那个(试图找出并理解错误),但不知怎的,我在这里得不到警告,它按预期工作(错误是从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;
}

What am I missing here and why are the two examples behaving differently? How do I get rid of the warning in the first example while still being able to propagate the error out of the lambda function? Any help would be appreciated.

我在这里错过了什么,为什么两个例子表现不同?如何在第一个示例中摆脱警告,同时仍然能够将错误传播出lambda函数?任何帮助,将不胜感激。

2 个解决方案

#1


4  

Any time you throw or reject within a promise/async function and don't handle it with a catch, Node is going to return that warning.

每当你在promise / async函数中抛出或拒绝并且不用catch来处理它时,Node就会返回该警告。

The example on AWS doesn't throw the error in the catch block, it returns it:

AWS上的示例不会在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;
};

In a large application with lots of asynchronous functions, having a single unhandled promise terminate the node process would be bad. That may not apply to a simple Lambda function where throwing an error that terminates the process is desired behavior. But if you don't want Node to warn you, return the error instead.

在具有大量异步函数的大型应用程序中,具有单个未处理的承诺终止节点进程将是错误的。这可能不适用于简单的Lambda函数,其中抛出终止进程的错误是期望的行为。但是,如果您不希望Node警告您,请返回错误。

#2


0  

I managed that by using the fail method from the context object that notifies Lambda function that the execution failed.

我通过使用上下文对象中的fail方法来管理它,该方法通知Lambda函数执行失败。

'use strict'

exports.handler = async function (event, context) {
  try {
    throw new Error('Something went wrong')
  } catch (err) {
    context.fail(err)
  }
}

分享到: