gpt4 book ai didi

node.js - DynamoDB 记录未通过 map 循环添加

转载 作者:行者123 更新时间:2023-12-02 11:17:56 25 4
gpt4 key购买 nike

我正在使用 Axios 从 API 获取价格(通常为数千),然后希望将其存储在 DynamoDB 中。如果我在本地调用 lambda 函数,一切都会按预期工作,但如果我部署该函数并使用 AWS CLI 调用它,它不再在 DynamoDB 中存储任何值。我在请求中收到的数据和 Axios 调用的响应是相同的。

我以某种方式认为这是调用 DynamoDB 的异步函数的范围问题,但我无法解决它。期待您的建议。如果您需要更多代码,请告诉我。

updatePrice.js

import { updatePrice } from "./libs/pricing-lib";
import {
success,
failure
} from "./libs/response-lib";

export async function main(event, context) {
try {
let result = await updatePrice(event.pathParameters.id, event.pathParameters.date);
return success(result);
} catch(e) {
return failure(e);
}
}

dynamodb-lib-js

import AWS from "aws-sdk";
export function call(action, params) {
const dynamoDb = new AWS.DynamoDB.DocumentClient();
return dynamoDb[action](params).promise();
}

定价-lib.js

export async function updatePrice(stockid, from) {
try {
let url = getUrl(stockid, from);
const resultEodApi = (await axios.get(url)).data;

resultEodApi.map((price) => {
try {
let priceParams = {
TableName: process.env.pricesTableName,
Item: {
stockid: stockid,
date: price.date,
close: price.close
}
};
dynamoDbLib.call("put", priceParams);
} catch (e) {
return e;
}
});

return true;
} catch (e) {
return e;
}
}

最佳答案

对 Ashish 的答案进行一些扩展。

问题:

正如 Ashish 所说,put 操作在 Lambda 部署中不起作用的原因是该调用是异步执行的。

dynamoDb[action](params).promise()的调用启动异步put操作,并返回一个Promise对象。当 put 操作返回时,promise 将被解析。

但是,在您的代码中,您既不等待 promise 得到解决,也不将 promise 作为处理程序的输出返回。对 updatePrice 的调用终止并返回 undefined,此时 AWS Lambda 暂停函数的执行。因此,put 调用永远不会通过。

为什么本地执行和远程执行之间存在差异?

您看到远程执行和本地执行之间存在差异的原因是本地 Node.js 进程和 Lambda 函数具有不同的语义。

当您在本地运行 Node.js 进程时,Node.js 进程仅在所有 Promise 都得到解决后才会终止1

Lambda 执行的行为有所不同。 Lambda 在终止执行之前不会等待 Promise 得到解决2。相反,Lambda 在解决处理程序返回的 Promise 后立即终止执行。在您的情况下,处理函数返回 true3,因此它会立即解析,并且执行终止。此时,您的 put 调用尚未解决。

为了说明差异,请考虑以下代码:

function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

module.exports.hello = async (event) => {
sleep(300).then(() => console.log("Finished doing my asynchronous thing, can exit now!"))
console.log("Function execution done!")
return true;
};

// call the handler when running locally:
if (require.main === module) { module.exports.hello(); }

当您在本地运行此函数时,函数执行完成,但 Node 进程仍在运行,直到 promise 得到解决。在本地运行,您将得到以下输出(注意顺序):

> Function execution done!
> Finished doing my asynchronous thing, can exit now!

在 lambda 上运行,当函数执行结束时,其余的运行也会结束。 promise 永远不会兑现。我们将得到以下输出:

START RequestId: <id> Version: $LATEST
2019-12-26T09:04:28.843Z <id> INFO Function execution done!
END RequestId: <id>
REPORT RequestId: <id> Duration: 3.37 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 71 MB Init Duration: 114.44 ms

我们只完成函数执行!打印。另请注意,执行持续时间仅为 3.37 毫秒。在 AWS 停止进程之前,我们异步运行的 300 毫秒 sleep 没有时间解决。

解决问题

来自AWS Lambda developer guide :

If your code performs an asynchronous task, return a promise to make sure that it finishes running. When you resolve or reject the promise, Lambda sends the response or error to the invoker.

您可以使用 Ashish 的解决方案——返回您创建的 promise 。或者,您可以显式await Promise.all。无论哪种情况,重要的是要确保在从函数返回之前不会丢失任何创建的 promise 。

<小时/>

1 更具体地说,它等待事件循环为空。

2 它实际上暂停了执行。下次调用处理程序时,将从同一位置继续执行。如果您对处理程序进行多次连续调用,则某些 put 可能会通过,具体取决于时间以及 aws-sdk 库处理执行流中此类中断的情况,但这很难预测。

3 实际上,async 函数的返回值始终是包装返回值的 Promise。因此,在您的情况下,您拥有的是 return true; - true 被包装在 Promise 对象中,该对象会立即解析,并且执行终止。

关于node.js - DynamoDB 记录未通过 map 循环添加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59420115/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com