节点 AWS Lambda 不执行某些异步代码
Node AWS Lambda not executing some asynchronous code
我在 AWS 上使用 Serverless Framework with the serverless-webpack
plugin, Prisma 和节点 12.x。我有几个 lambda,每个执行一些异步代码,但有些代码似乎没有执行(或承诺履行)。该代码在本地完美运行,但部署在 AWS 上时就不行了。
内嵌相关注释的 lambda 示例:
"use strict";
import { PrismaClient } from "@prisma/client";
import fetch from "node-fetch";
const prisma = new PrismaClient();
module.exports.handler = async (event, context, callback) => {
try {
const users = await prisma.user.findMany();
console.log(`Users: ${JSON.stringify(users)}`); // shows properly in Lambda logs
users.map(async (user) => {
const res = await fetch(`...`); // doesn't seem to execute on AWS but does locally
const data = await res.json();
const query = await prisma.user.update({...}); // doesn't seem to execute on AWS but does locally
console.log(data); // doesn't show up in Lambda logs
console.log(query); //doesn't show up in Lambda logs
});
// shows properly in Lambda logs
console.log(
`Completed ${context.functionName} at ${new Date().toLocaleString()}`
);
} catch (err) {
console.log(`ERROR: ${context.functionName} failed with error ${err}`);
}
};
webpack.config.js
:
const path = require("path");
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
context: __dirname,
mode: slsw.lib.webpack.isLocal ? "development" : "production",
entry: slsw.lib.entries,
devtool: slsw.lib.webpack.isLocal
? "cheap-module-eval-source-map"
: "source-map",
resolve: {
extensions: [".mjs", ".json", ".ts"],
symlinks: false,
cacheWithContext: false,
},
output: {
libraryTarget: "commonjs",
path: path.join(__dirname, ".webpack"),
filename: "[name].js",
},
target: "node",
externals: [nodeExternals()],
module: {
rules: [
// all files with `.ts` or `.tsx` extension handled by `ts-loader`
{
test: /\.(tsx?)$/,
loader: "ts-loader",
exclude: [
[
path.resolve(__dirname, "node_modules"),
path.resolve(__dirname, ".serverless"),
path.resolve(__dirname, ".webpack"),
],
],
options: {
transpileOnly: true,
experimentalWatchApi: true,
},
},
],
},
plugins: [
new CopyWebpackPlugin({ patterns: ["prisma/schema.prisma"] }),
],
};
我也尝试过不使用 try/catch 块,并增加了 serverless.yml
中的 lambda 超时。我认为这可能与嵌套异步 (user.map(async ...)
) 有关,但我不确定。 lambda 的 CloudWatch 日志没有显示任何错误,并且只显示代码中所示的映射函数之外的 console.log()
s。任何帮助是极大的赞赏。非常感谢!
编辑: 我现在在 CloudWatch 日志中收到一个错误:ERROR: [LAMBDA_NAME] failed with error FetchError: request to [ENDPOINT] failed, reason: connect ETIMEDOUT [IP_ADDRESS]:443.
不过,我认为这是一个单独的问题。解决方案是按照@CyberEternal 的建议将 users.map(async (user) => {...}
更改为 for (const user of users) {...}
。
与地图中的异步功能相关的问题。实际上,这是行不通的。您可以尝试“for”循环。 100% 有效。
试试这个方法
"use strict";
import { PrismaClient } from "@prisma/client"; import fetch from "node-fetch";
const prisma = new PrismaClient();
module.exports.handler = async (event, context, callback) => { try {
const users = await prisma.user.findMany();
console.log(`Users: ${JSON.stringify(users)}`); // shows properly in Lambda logs
for (const user of users) {
console.log('user: ', user); // doesn't show up in Lambda logs
const res = await fetch(`...`); // doesn't seem to execute on AWS but does locally
const data = await res.json();
const query = await prisma.user.update({ ...}); // doesn't seem to execute on AWS but does locally
console.log('data: ', data); // doesn't show up in Lambda logs
console.log('query: ', query); //doesn't show up in Lambda logs
}
// shows properly in Lambda logs
console.log(
`Completed ${context.functionName} at ${new Date().toLocaleString()}`
); } catch (err) {
console.log(`ERROR: ${context.functionName} failed with error ${err}`); } };
而且如果你对更新过程使用一个单独的函数会更好。
像这样
"use strict";
import { PrismaClient } from "@prisma/client";
import fetch from "node-fetch";
const prisma = new PrismaClient();
module.exports.handler = async (event, context, callback) => {
try {
const users = await prisma.user.findMany();
console.log(`Users: ${JSON.stringify(users)}`); // shows properly in Lambda logs
await updateUser(users);
// shows properly in Lambda logs
console.log(
`Completed ${context.functionName} at ${new Date().toLocaleString()}`
);
} catch (err) {
console.log(`ERROR: ${context.functionName} failed with error ${err}`);
}
};
const updateUser = async users => {
if (!users || !users.length) throw new Error('Users not found');
for (const user of users) {
console.log('user: ', user); // doesn't show up in Lambda logs
const res = await fetch(`...`); // doesn't seem to execute on AWS but does locally
const data = await res.json();
const query = await prisma.user.update({ ...}); // doesn't seem to execute on AWS but does locally
console.log('data: ', data); // doesn't show up in Lambda logs
console.log('query: ', query); //doesn't show up in Lambda logs
}
return 'Updated'
}
我在 AWS 上使用 Serverless Framework with the serverless-webpack
plugin, Prisma 和节点 12.x。我有几个 lambda,每个执行一些异步代码,但有些代码似乎没有执行(或承诺履行)。该代码在本地完美运行,但部署在 AWS 上时就不行了。
内嵌相关注释的 lambda 示例:
"use strict";
import { PrismaClient } from "@prisma/client";
import fetch from "node-fetch";
const prisma = new PrismaClient();
module.exports.handler = async (event, context, callback) => {
try {
const users = await prisma.user.findMany();
console.log(`Users: ${JSON.stringify(users)}`); // shows properly in Lambda logs
users.map(async (user) => {
const res = await fetch(`...`); // doesn't seem to execute on AWS but does locally
const data = await res.json();
const query = await prisma.user.update({...}); // doesn't seem to execute on AWS but does locally
console.log(data); // doesn't show up in Lambda logs
console.log(query); //doesn't show up in Lambda logs
});
// shows properly in Lambda logs
console.log(
`Completed ${context.functionName} at ${new Date().toLocaleString()}`
);
} catch (err) {
console.log(`ERROR: ${context.functionName} failed with error ${err}`);
}
};
webpack.config.js
:
const path = require("path");
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
context: __dirname,
mode: slsw.lib.webpack.isLocal ? "development" : "production",
entry: slsw.lib.entries,
devtool: slsw.lib.webpack.isLocal
? "cheap-module-eval-source-map"
: "source-map",
resolve: {
extensions: [".mjs", ".json", ".ts"],
symlinks: false,
cacheWithContext: false,
},
output: {
libraryTarget: "commonjs",
path: path.join(__dirname, ".webpack"),
filename: "[name].js",
},
target: "node",
externals: [nodeExternals()],
module: {
rules: [
// all files with `.ts` or `.tsx` extension handled by `ts-loader`
{
test: /\.(tsx?)$/,
loader: "ts-loader",
exclude: [
[
path.resolve(__dirname, "node_modules"),
path.resolve(__dirname, ".serverless"),
path.resolve(__dirname, ".webpack"),
],
],
options: {
transpileOnly: true,
experimentalWatchApi: true,
},
},
],
},
plugins: [
new CopyWebpackPlugin({ patterns: ["prisma/schema.prisma"] }),
],
};
我也尝试过不使用 try/catch 块,并增加了 serverless.yml
中的 lambda 超时。我认为这可能与嵌套异步 (user.map(async ...)
) 有关,但我不确定。 lambda 的 CloudWatch 日志没有显示任何错误,并且只显示代码中所示的映射函数之外的 console.log()
s。任何帮助是极大的赞赏。非常感谢!
编辑: 我现在在 CloudWatch 日志中收到一个错误:ERROR: [LAMBDA_NAME] failed with error FetchError: request to [ENDPOINT] failed, reason: connect ETIMEDOUT [IP_ADDRESS]:443.
不过,我认为这是一个单独的问题。解决方案是按照@CyberEternal 的建议将 users.map(async (user) => {...}
更改为 for (const user of users) {...}
。
与地图中的异步功能相关的问题。实际上,这是行不通的。您可以尝试“for”循环。 100% 有效。
试试这个方法
"use strict";
import { PrismaClient } from "@prisma/client"; import fetch from "node-fetch";
const prisma = new PrismaClient();
module.exports.handler = async (event, context, callback) => { try {
const users = await prisma.user.findMany();
console.log(`Users: ${JSON.stringify(users)}`); // shows properly in Lambda logs
for (const user of users) {
console.log('user: ', user); // doesn't show up in Lambda logs
const res = await fetch(`...`); // doesn't seem to execute on AWS but does locally
const data = await res.json();
const query = await prisma.user.update({ ...}); // doesn't seem to execute on AWS but does locally
console.log('data: ', data); // doesn't show up in Lambda logs
console.log('query: ', query); //doesn't show up in Lambda logs
}
// shows properly in Lambda logs
console.log(
`Completed ${context.functionName} at ${new Date().toLocaleString()}`
); } catch (err) {
console.log(`ERROR: ${context.functionName} failed with error ${err}`); } };
而且如果你对更新过程使用一个单独的函数会更好。 像这样
"use strict"; import { PrismaClient } from "@prisma/client"; import fetch from "node-fetch"; const prisma = new PrismaClient(); module.exports.handler = async (event, context, callback) => { try { const users = await prisma.user.findMany(); console.log(`Users: ${JSON.stringify(users)}`); // shows properly in Lambda logs await updateUser(users); // shows properly in Lambda logs console.log( `Completed ${context.functionName} at ${new Date().toLocaleString()}` ); } catch (err) { console.log(`ERROR: ${context.functionName} failed with error ${err}`); } }; const updateUser = async users => { if (!users || !users.length) throw new Error('Users not found'); for (const user of users) { console.log('user: ', user); // doesn't show up in Lambda logs const res = await fetch(`...`); // doesn't seem to execute on AWS but does locally const data = await res.json(); const query = await prisma.user.update({ ...}); // doesn't seem to execute on AWS but does locally console.log('data: ', data); // doesn't show up in Lambda logs console.log('query: ', query); //doesn't show up in Lambda logs } return 'Updated' }