重构 node.js(第 2 部分)
内容
1. 使用严格模式尽早失败
2. 使用 linting 工具
3. 编写 JSDoc 文档
4. 使用 fs.promise 的异步 FS 方法
5. 必须全部捕获:使用全局错误处理程序
有什么想法吗?💬
欢迎阅读“重构 Node.js”系列的第二部分。在本系列中,我将分享一些技巧和工具,我相信它们能帮助你编写更高效、更简洁的 Node.js 代码。
内容
1. 使用严格模式尽早失败
我在 Github 上阅读mongoose的代码时发现了严格模式。我真的很好奇,为什么整个库里的每个文件都以 开头?'use strict'
ECMAScript 5 在 JavaScript 中引入了严格模式。当我们应用严格模式时,我们可以更容易地编写更干净、更安全的代码,因为 JavaScript 的宽松程度降低了:
- 我们无法逃避诸如未声明变量之类的事情:
'use strict'
undeclaredVar = 10; // Throws an error.
let
不允许使用名称与 Javascript 关键字匹配的变量:
'use strict'
var let = 10; // Throws an error.
- 函数中的所有参数必须具有唯一的名称:
'use strict'
// Throws an error.
function sum (a, a) {
}
我们如何在代码中使用严格模式?
我们可以通过use strict
在任何 Javascript 文件中写入来“激活”严格模式
'use strict'
// JS Code.
或者,如果我们愿意,我们可以在特定的功能中使用它:
function strictFunction() {
'use strict'
// Function code.
}
function notStrictFunction() {
// Function code.
}
有趣的事实:Javascript模块默认是严格的,所以我们不需要明确应用严格模式。
module.exports.noNeedForUseStrict = () => {
// Strict mode by default.
}
为什么要使用严格模式?
通过避免我之前提到的那些(以及更多)问题,我们可以更轻松地编写出更安全、故障概率更低的代码。当我们编写不安全的代码时,我们会立即收到警报,而及早发现问题可以防止我们犯下小错误,这也有助于我们学习和应用更好的实践。
有关严格模式的更多信息:MDN - 严格模式。
2. 使用 linting 工具
我以前写 JavaScript 时最烦人的问题之一就是总是在字符串的单引号和双引号之间切换。后来我读了 ESLint 的相关知识,经过一些设置后,我就能确保所有字符串都使用单引号了。
使用像 ESLint 这样的 linting 工具将帮助你:
- 为您和您的团队设置样式规则,使代码保持标准化并且团队中的任何人都可以轻松阅读。
- 发现未使用的变量等错误
- 轻松遵循预定义的样式指南,让您的代码更易于阅读,不仅对您和您的团队如此。例如:Google JavaScript 样式指南。
安装 ESLint
- 执行
npm install eslint --save-dev
你的项目 - CLI 将帮助你设置基本配置
您还可以通过编辑文件来自定义默认配置.eslint.js
。
运行 ESLint
设置样式规则后,剩下要做的就是运行 ESLint 并开始修复它可能发现的任何问题。
要在整个项目中运行 ESLint:eslint ./
此命令将扫描您的代码,并告知您是否在某个地方未遵循您设置的规则。它还会为您提供错误代码、错误所在的行以及问题的简要描述:
const myConst = 10;
myConst = 11;
// ESLint result:
// 2:1 error 'myConst' is constant no-const-assign
如果描述不够好,您可以随时使用错误代码通过ESLint 网站中的搜索字段来查看问题的深入解释。
但请稍等,还有更多!
您可以使用此选项应用自动修复--fix
。这并不能解决所有问题,因为有些问题可能需要人工干预,但它可以解决很多问题,使重构过程更加轻松。
我还写了关于在 CI 管道中运行 ESlint 的文章。
3. 编写 JSDoc 文档
JSDoc 是一个开源的 JavaScript API 文档生成器。它允许开发人员通过注释来记录他们的代码。
以下是使用 JSDoc 记录的函数的样子:
/**
* Retrieves a user by email.
* @async
* @param {String} email - User email
* @returns {User} User object
* @throws {NotFoundError} When the user is not found.
*/
const getByEmail = async (email) => {
// ...
}
JSDoc 有什么好处?
- 您可以使用大量的标签列表(例如)来尽可能详细地记录您的代码
@param
。 - 记录代码后,您可以使用一个简单的命令将文档导出到 HTML 网站:
jsdoc r
- 它在 VSCode 中具有内置支持
- 导出的网站布局可以自定义,Github 上有可用的模板。
- 即使您不导出它,该文档对于阅读您的代码的任何人都有帮助(特别是如果您使用 VSCode 或任何支持 JSDoc 的 IDE)。
如果你想了解更多关于 JSDoc 的知识,我写了一篇关于这个主题的文章:使用 JSDoc 记录你的 JavaScript 代码
4. 使用 fs.promise 的异步 FS 方法
上次我写了关于util.promisify
如何使用它将回调模块转换为 Promise 的文章。但后来@hugo__dffs
在评论中指出了一点:
因此,自从 Node.js v10 以来,我们就可以fs
像这样使用承诺:
const fs = require('fs').promises;
const readFile = async (path) => {
// Check if the path exists.
const stats = await fs.stat(path);
// Check if the path belongs to a file.
if (!stats.isFile())
throw new Error('The path does not belong to a file');
// Read file.
return await fs.readFile(path);
}
不再需要util.promisify
操作fs
!
5. 必须全部捕获:使用全局错误处理程序
在我的上一篇文章中,我写了关于使用描述性错误类型来使我们的错误更容易识别和处理,你们中的一些人要求我写更多关于错误处理的内容,所以让我们来谈谈全局错误处理。
什么是全局错误处理?
全局错误处理使我们能够在一个地方捕获所有错误。这是捕获错误并决定如何处理的最后一道屏障。
拥有全局错误处理程序有很多优点:
- 我们可以定义标准规则来处理始终会应用的错误。
- 用户或客户端永远不会收到完全未处理的错误。
- 所有错误都可以记录在某处,甚至在发生错误时通知团队。
- 它确保我们不会向客户端发送任何私人信息(如表名),从而保证我们软件的安全。
- 开发环境需要比生产环境更多的错误信息。我们可以确保我们的软件能够让开发人员了解错误的详细信息,而不会将所有信息暴露给用户或客户端。
- 客户端或用户需要清晰的错误信息才能采取相应的措施。良好的全局错误处理程序实现能够确保这一点。
- 实际上,我们可以决定如何处理可能被任何人发现的错误。
我们如何实现它?
全局错误处理程序的实现取决于我们编写的软件类型,特别是因为 Node.js 可用于构建 REST API、CLI、作业等。
如果您正在使用框架,您可能会发现它已经考虑了全局错误处理程序的定义,因此我鼓励您检查文档。
让我们以 Express.js 为例。
Express.js 中的错误处理
Express.js 是 Node.js 的 Web 框架,它有自己的错误处理策略,您可以利用它。
要使用 express 处理所有错误,我们需要使用中间件。一个简单的中间件如下所示:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello world!');
});
// Define the error handler after other middleware and endpoints.
app.use(errorHandler)
app.listen(port);
/**
* Error handling middleware.
*/
function errorHandler(err, req, res, next) {
logError(err);
if (err.statusCode) {
// All errors that have a status code are safe.
res.status(err.statusCode).send({ error: err.message });
}
else {
res.status(500).send({ error: 'Something went wrong' });
}
}
如您所见,我们在这里所做的是捕获可能发生的任何错误并定义以下非常简单的规则:
- 所有错误都记录在某处。
- 如果我们的错误有一个
statusCode
,我们假设可以安全地将其返回给客户端,并使用错误中定义的相同状态代码和消息。 - 如果我们的错误没有
statusCode
,我们将返回状态代码为 500(内部服务器错误)的通用消息。
即使在这个非常简单的例子中,我们也已经确保不会向客户端返回任何未处理的错误,所有错误都会被记录下来,以便我们稍后评估是否需要修复,并且客户端能够收到足够的信息来采取相应的措施。我们的软件安全可靠,客户也非常满意。
错误处理工具
在前面的例子中,我们编写了一个自定义的全局错误处理程序,用于将错误记录到某个地方。这可能足以在项目早期阶段处理错误,但我们最终可能需要更多功能。例如,如果能够收到应用程序抛出的错误的通知和报告,以便我们快速采取行动修复它们,那就太好了。
短篇故事:我和 @maurogarcia_19 启动我们最新的项目Cephhi时,遇到了一个可怕的 bug,它只出现在非英语浏览器上。这个错误被记录下来了,但我们首先从用户那里得知了它。如果我们收到了自动通知,我们就能更快地修复错误,减少受影响的用户数量。吸取了教训!
市面上有很多用于错误监控和报告的工具。我目前正在尝试Bugsnag。目前为止,我喜欢它的地方在于:
- 与 JavaScript 集成非常容易
- 它有一个适合小型企业的免费计划
- 它可以与 Slack 集成,因此每次出现错误时您都会收到一条消息和一组要执行的“操作”。
你尝试过其他工具吗?告诉我!
有什么想法吗?💬
这些提示有用吗?
您希望我在本系列的下一篇文章中撰写有关其他 node.js 的主题吗?
您有什么技巧可以编写有效/干净的 node.js 代码?
我很乐意听取您的反馈!
鏂囩珷鏉ユ簮锛�https://dev.to/paulasantamaria/refactoring-node-js-part-2-f0b
Node 10+ 在 fs.promises 下有一个 fs 的 promisified 版本。