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.fetchAll
和teamModel.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/await
forEach
不使用 AWSSDK 的 .promise()
您知道 AWS SDK 客户端同时支持回调和 Promise 吗?要使用async/await
AWS 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