【问题标题】:Attempting to check if s3 bucket item exists within nested asyncs尝试检查嵌套异步中是否存在 s3 存储桶项
【发布时间】:2019-05-13 15:26:59
【问题描述】:

我有一个无服务器 Lambda 函数,它响应 S3 s3:ObjectCreated 事件,尝试使用 AWS JavaScript SDK 使用以下代码检查 S3 存储桶中是否存在单独的项目:

exports.somethingSomeSomething = async (event) => {

  event.Records.forEach(async (record) => {

    let tst = await s3.headObject({
      Bucket: "mybucket",
      Key: "something.gz"
    }).promise()

    console.log(tst)
  })

};

我对 JS 中的 Promise 很生疏,所以我不确定为什么这段代码不起作用。作为参考,它只是死了,没有输出任何东西。

但是,以下确实有效:

exports.somethingSomething = async (event) => {


    let tst = await s3.headObject({
      Bucket: "mybucket",
      Key: "something.gz"
    }).promise()

    console.log(tst)
    console.log("RED")

};

我怎样才能让最初的代码工作,我做错了什么?

【问题讨论】:

    标签: amazon-s3 async-await es6-promise serverless-framework


    【解决方案1】:

    这是因为你的代码是async,但传递给forEach循环的函数也是async,所以你有一个async函数调用另一块async代码,因此你失去了控制流量。 forEach 中的任何内容都将运行(尽管forEach 之后的任何内容都将在forEach 中的任何内容之前运行),但它将异步执行,您无法跟踪其执行情况。

    但是如果代码,如我所说,会运行,为什么你看不到结果?

    嗯,这是因为 Lambda 将在该代码有机会执行之前终止。如果您在本地运行同一段代码,您会发现它运行良好,但由于原始代码运行在 Lambda 之上,您无法控制它何时终止。

    这里有两个选择:

    最简单的方法是获取 Records 数组中的第一项,因为 s3 事件每次调用发送一个且仅发送一个事件。它是一个数组的原因是因为 AWS 的工作方式(所有事件的通用接口)。无论如何,您的 forEach 没有使用 Record 对象的任何内容,但如果您想使用它的任何属性,只需引用第 0 个位置,如下所示:

    exports.somethingSomeSomething = async (event) => {
        const record = event.Records[0]
    
        //do something with record
    
        const tst = await s3.headObject({
            Bucket: "mybucket",
            Key: "something.gz"
        }).promise()
    
        console.log(tst)
    };
    

    如果您仍想使用 for 循环来遍历记录(尽管同样对于 s3 事件来说是不必要的),请改用 for of 循环:

    exports.somethingSomeSomething = async (event) => {
        for (const record of event.Records) {
            // do something with record
            const tst = await s3.headObject({
                Bucket: "mybucket",
                Key: "something.gz"
            }).promise()
            console.log(tst)
        }
    };
    

    由于for of 只是一个常规循环,它将使用正在执行的函数中的async,因此await 在其中完全有效。

    更多关于async/awaitfor..of

    【讨论】:

    • 很好的答案,谢谢!无循环场景似乎最适合我的特定用例。也就是说,我想知道为什么 它会为 Lambda 终止? Lambda 的这种行为记录在哪里?
    • 谢谢!从理论上讲,您应该能够通过在 context 对象上将 'callbackWaitsForEmptyEventLoop' 设置为 true 来修改此行为,但这是回调样式的旧解决方法。我个人从未测试过它是否适用于async/await。 IIRC,回调和承诺在事件循环中设置在不同的数组中,所以我认为callbackWaitsForEmptyEventLoop 只查看是否有任何待处理的回调,所以我盲目猜测它不会起作用。
    • 讨论这些属性的文档位于:docs.aws.amazon.com/lambda/latest/dg/…
    猜你喜欢
    • 2016-11-12
    • 1970-01-01
    • 2015-07-27
    • 2020-11-06
    • 2013-09-06
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 2016-02-23
    相关资源
    最近更新 更多