节点 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. 不过,我认为这是一个单独的问题。解决方案是按照@Cyber​​Eternal 的建议将 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'
}