Common Node.js mistakes in Lambda Still using callbacks Not using promisify Too sequential async/await inside forEach() Not using AWSSDK’s .promise() Wrap-up

2025-06-07

Lambda 中常见的 Node.js 错误

仍在使用回调

不使用promisify

过于连续

forEach() 中的 async/await

不使用 AWSSDK 的 .promise()

包起来

我帮助过不少客户开发 Node.js 无服务器项目。在开发过程中,我发现了一些反复出现的错误async/await

仍在使用回调

许多人仍在异步处理程序函数中使用回调:

module.exports.handler = async (event, context, cb) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({ message: 'hello world' })
  }

  cb(null, response)
}

而不是更简单的替代方案:

module.exports.handler = async (event, context) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({ message: 'hello world' })
  }

  return response
}

不使用promisify

在 Node 8 之前,Bluebird填补了一个巨大的空白。它提供了将基于回调的函数转换为基于 Promise 的函数的功能。但 Node 8 的内置util模块已经用函数填补了这一空白promisify

例如,我们现在可以像这样转换模块readFile中的函数:fs

const fs = require('fs')
const { promisify } = require('util')
const readFile = promisify(fs.readFile)

不再需要使用 Bluebird 了。这样就少了一个依赖,有助于减少函数的冷启动时间。

过于连续

async/await让你可以像写同步代码一样编写异步代码,太棒了。再也不用忍受回调地狱了!

另一方面,我们也可能会错过一些技巧,并且无法在适当的时候同时执行任务。

以下面的代码为例:

async function getFixturesAndTeam(teamId) {
  const fixtures = await fixtureModel.fetchAll()
  const team = await teamModel.fetch(teamId)
  return {
    team,
    fixtures: fixtures.filter(x => x.teamId === teamId)
  }
}

这个函数很容易理解,但它并不是最优的。teamModel.fetch不依赖于的结果fixtureModel.fetchAll,所以它们应该同时运行。

您可以按照以下方法进行改进:

async function getFixturesAndTeam(teamId) {
  const fixturesPromise = fixtureModel.fetchAll()
  const teamPromise = teamModel.fetch(teamId)

  const fixtures = await fixturesPromise
  const team = await teamPromise

  return {
    team,
    fixtures: fixtures.filter(x => x.teamId === teamId)
  }
}

在这个版本中,fixtureModel.fetchAllteamModel.fetch同时启动。

map使用with时也需要注意async/await。下面会teamModel.fetch依次调用:

async function getTeams(teamIds) {
  const teams = _.map(teamIds, id => await teamModel.fetch(id))
  return teams
}

相反,您应该将其写成如下形式:

async function getTeams(teamIds) {
  const promises = _.map(teamIds, id => teamModel.fetch(id))
  const teams = await Promise.all(promises)
  return teams
}

在这个版本中,我们映射teamIds到一个数组Promise。然后我们可以使用将此数组转换为返回团队数组的Promise.all单精度数组。Promise

在这种情况下,teamModel.fetch被并发调用并且可以显著提高执行时间。

forEach() 中的 async/await

这是一个棘手的问题,有时甚至会让经验丰富的 Node.js 开发人员感到困惑。

问题是这样的代码并不像你期望的那样运行:

[ 1, 2, 3 ].forEach(async (x) => {
  await sleep(x)
  console.log(x)
})

console.log('all done.')

运行此程序时,您将获得以下输出:

all done.

请参阅这篇文章,详细解释为什么这不起作用。目前,只需记住避免在!内部使用即可。async/awaitforEach

不使用 AWSSDK 的 .promise()

您知道 AWS SDK 客户端同时支持回调和 Promise 吗?要使用async/awaitAWS SDK,请.promise()按如下方式添加到客户端方法中:

const AWS = require('aws-sdk')
const Lambda = new AWS.Lambda()

async function invokeLambda(functionName) {
  const req = {
    FunctionName: functionName,
    Payload: JSON.stringify({ message: 'hello world' })
  }
  await Lambda.invoke(req).promise()
}

不再有回调函数,耶!

包起来

以上就是在 Lambda 中使用 Node.js 时需要避免的 5 个常见错误。关注我,了解更多关于构建生产级无服务器应用程序的技巧和最佳实践。

请访问theburningmonk.com查看我的更多文章。

文章来源:https://dev.to/theburningmonk/common-node-js-mistakes-in-lambda-4a4j
PREV
编码训练营的现实
NEXT
分解 Async/Await