TypeScript async/await最佳实践:Express代码冗余写法疑问
关于ExpressJS+TypeScript中async/await嵌套使用的最佳实践疑问
我在ExpressJS中使用TypeScript开发密码找回功能,编写了如下精简代码,现在有个疑问:执行const results = await checkForEmailAddress(email);时,调用async函数前使用了await,而该函数内部也采用了async/await写法,想确认这种做法是否符合最佳实践,是否存在冗余。
/** * Verifies that an email address exists in the DB. * If so, sends them an email to recover their password. * * @param {Request} req * @param {Response} res */ const sendPasswordRecoveryEmail = (req: Request, res: Response) => { const email = req.body.email const checkForEmailAddress = async (email: string) => { return await pool.query(`SELECT password FROM users WHERE email = $1`, [email]); }; const updatePasswordFields = async (password: string, newPassword: string, email: string) => { return await pool.query(`UPDATE users SET last_password = $1, password = $2 WHERE email = $3`, [password, newPassword, email]); }; const passwordRecoveryProcess = async (email: string) => { try { res.status(200).send({ status: true, message: 'Password recovery process initiated.' }); const results = await checkForEmailAddress(email); if (results.rows.length === 1) { const existingPassword = results.rows[0].password; const newTempPassword = generateRandomPassword(); await updatePasswordFields(existingPassword, newTempPassword, email); const body = `...`; emailService({email, subject: 'MySite Password Recovery', body}); } } catch (error) { console.error('Error', error); } } passwordRecoveryProcess(email); // Initiate async Password Recovery Process };
回答
这种写法符合最佳实践,不存在功能上的冗余,具体解释如下:
- 外层调用
checkForEmailAddress时使用await是必要的:因为checkForEmailAddress是async函数,返回的是一个Promise,只有用await才能等待这个Promise完成,拿到实际的数据库查询结果,否则后续判断results.rows.length会因为拿到Pending状态的Promise而报错。 - 内部函数里的
await本身是合理的:pool.query是异步操作,返回Promise,内部用await是为了等待数据库操作完成,确保函数返回的是查询结果的Promise。不过这里可以做简洁化优化:因为pool.query已经返回Promise,async函数会自动将返回值包装为Promise,所以可以去掉内部的await,直接返回pool.query的结果,效果完全一致,比如:
甚至可以去掉async关键字,直接返回Promise:const checkForEmailAddress = async (email: string) => { return pool.query(`SELECT password FROM users WHERE email = $1`, [email]); };
这两种优化写法和原代码功能完全相同,但更简洁。原代码的写法虽然多了一层await包装,但不会影响功能和性能,只是略显冗余,并非错误写法。const checkForEmailAddress = (email: string) => { return pool.query(`SELECT password FROM users WHERE email = $1`, [email]); };
内容的提问来源于stack exchange,提问作者RobertW
相关产品推荐
相关产品推荐

