【问题标题】:Lambda forgot how to interpret JavaScript?Lambda 忘记了如何解释 JavaScript?
【发布时间】:2020-04-07 05:20:41
【问题描述】:

我在 Lambda 中发生了一些非常奇怪的事情。我有一个解释字符串输入的 JS 函数。此代码由单元测试覆盖,以确认验证逻辑按预期工作。但是一旦将它部署到 Lambda,我就会得到不同的行为。我是否忽略了一个真正的菜鸟错误。或者 Lambda 中是否有一些设置可以解释为什么我的代码被不同地解释。

这是我的功能:

public async processMessage(message: string): Promise<void> {
    logger.info(`Message: ${message}`);
    const params = JSON.parse(message);


    if ('fileId' in params && 'location' in params && 'fileType' in params) {
        return this.fileLoader.load(params.fileId, params.location, fromString(params.fileType));
    } else {
        throw new InvalidArgumentError('A required field on the message is missing.');
    }
}

验证按预期工作,函数被正确调用。一切似乎都很棒! 然后我将它部署到 lambda 并在那里调用它。我收到此错误:

Cannot use 'in' operator to search for 'fileId' in {\"fileId\":\"1234\",\"fileType\": \"TEST_FILE\",\"location\": \"https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv\"}

这是 CloudWatch 日志:

Message: "{\"fileId\":\"1234\",\"fileType\": \"TEST_FILE\",\"location\": \"https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv\"}"
ERROR   Unhandled Promise Rejection     
{
    "errorType": "Runtime.UnhandledPromiseRejection",
    "errorMessage": "TypeError: Cannot use 'in' operator to search for 'fileId' in {\"fileId\":\"1234\",\"fileType\": \"TEST_FILE\",\"location\": \"https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv\"}",
    "reason": {
        "errorType": "TypeError",
        "errorMessage": "Cannot use 'in' operator to search for 'fileId' in {\"fileId\":\"1234\",\"fileType\": \"TEST_FILE\",\"location\": \"https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv\"}",
        "stack": [
            "TypeError: Cannot use 'in' operator to search for 'fileId' in {\"fileId\":\"1234\",\"fileType\": \"TEST_FILE\",\"location\": \"https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv\"}",
            "    at FileLoaderMessageHandler.processMessage (/var/task/dist/infrastructure/fileLoaderMessageHandler.js:14:22)",
            "    at /var/task/dist/aws/fileLoader.js:23:57",
            "    at Array.forEach (<anonymous>)",
            "    at Runtime.exports.handle [as handler] (/var/task/dist/aws/fileLoader.js:23:18)",
            "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
        ]
    },
    "promise": {},
    "stack": [
        "Runtime.UnhandledPromiseRejection: TypeError: Cannot use 'in' operator to search for 'fileId' in {\"fileId\":\"1234\",\"fileType\": \"TEST_FILE\",\"location\": \"https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv\"}",
        "    at process.<anonymous> (/var/runtime/index.js:35:15)",
        "    at process.emit (events.js:210:5)",
        "    at process.EventEmitter.emit (domain.js:476:20)",
        "    at processPromiseRejections (internal/process/promises.js:201:33)",
        "    at processTicksAndRejections (internal/process/task_queues.js:94:32)"
    ]
}

我尝试重构它以使用 Object.keys。但它的表现仍然很奇怪。

function isFileLoaderParams(params: any): params is FileLoaderParams {
    logger.info(`INPUT: ${params}`);

    if (!params.fileId) {
        logger.warn('FileId not found');
        logger.info(`DoubleCheck: ${JSON.stringify(params)}`);
        logger.info(`Value Is: ${JSON.stringify(params.fileId)}`);
        logger.info(`ArrayAccess?: ${JSON.stringify(params['fileId'])}`);
        return false;
    }

    if (!params.location) {
        logger.warn('Location not found');
        return false;
    }

    if (!params.fileType) {
        logger.warn('FileType not found');
        return false;
    }

    return true;
}

生成此输出:

INPUT: {"fileId":"1234","fileType": "TEST_FILE","location": "https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv"}
FileId not found
DoubleCheck: "{\"fileId\":\"1234\",\"fileType\": \"TEST_FILE\",\"location\": \"https://d4-file-proc-staging.s3.amazonaws.com/testFile.csv\"}"
Value Is: undefined
ArrayAccess?: undefined

配置/环境详情

  • 用打字稿写的
  • tsc 使用 Typescript 8.3.0 编译
  • 使用无服务器框架部署
  • Lambda 运行时:Node.js 12.x(也在 Node 10 中运行,但升级到 12 试图修复此问题)

【问题讨论】:

  • 看起来params 是一个字符串,您必须使用const params = JSON.parse(JSON.parse(message)); 或确保您发送的是有效的JSON。

标签: javascript typescript aws-lambda


【解决方案1】:

该错误意味着paramsString,而不是对象。也许您的message 是一个双重编码的 JSON 字符串(一个包含 JSON 字符串的 JSON 字符串)。我不确定它是如何到达那里的,但是寻找在已经是 JSON 的东西上执行 JSON.stringify 的逻辑。或者正如@Titus 提到的,做一个双重解码:

const params = JSON.parse(JSON.parse(message));

【讨论】:

  • 我什至没有考虑过双重编码。不知道那是一回事。我所看到的只是“致电JSON.parse”,但我以为我已经知道了。
猜你喜欢
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-14
  • 2012-04-21
  • 2011-09-06
  • 1970-01-01
相关资源
最近更新 更多