面试题答案
一键面试错误处理
- 路由错误处理:
- 使用
next
函数:在路由处理函数中,如果遇到不符合预期的请求(例如请求的参数格式不正确等),可以调用next
函数并传入一个错误对象。例如:
const express = require('express'); const app = express(); app.get('/user/:id', (req, res, next) => { const id = parseInt(req.params.id); if (isNaN(id)) { const err = new Error('Invalid user ID'); err.status = 400; next(err); } else { // 正常处理逻辑 res.send(`User ID: ${id}`); } });
- 全局错误处理中间件:定义一个全局错误处理中间件,放在所有路由和其他中间件之后。这个中间件接收四个参数:
err
(错误对象)、req
(请求对象)、res
(响应对象)和next
(next
函数,虽然在这里通常不使用)。
app.use((err, req, res, next) => { console.error(err.stack); if (!err.status) { err.status = 500; } res.status(err.status).send(err.message); });
- 使用
- 运行时错误处理:
- 使用
try - catch
块:在可能抛出运行时错误(如数据库查询失败、文件读取错误等)的异步操作中,使用try - catch
块捕获错误并通过next
传递给全局错误处理中间件。例如,使用async/await
进行数据库查询:
const { Pool } = require('pg'); const pool = new Pool({ user: 'user', host: 'host', database: 'database', password: 'password', port: 5432, }); app.get('/data', async (req, res, next) => { try { const result = await pool.query('SELECT * FROM some_table'); res.send(result.rows); } catch (err) { next(err); } });
- Promise 链中的错误处理:如果使用Promise进行异步操作,可以在Promise链的末尾使用
.catch
方法捕获错误并传递给next
。例如:
app.get('/data', (req, res, next) => { pool.query('SELECT * FROM some_table') .then(result => { res.send(result.rows); }) .catch(err => { next(err); }); });
- 使用
性能优化
- 中间件的使用:
- 精简中间件数量:只使用必要的中间件,避免引入过多不必要的功能。例如,如果应用不需要处理静态文件,就不要引入
express - static
中间件。 - 合理排序中间件:中间件的执行顺序很重要。例如,
body - parser
中间件应该放在路由定义之前,以便在路由处理函数中能够正确获取请求体数据。安全相关的中间件(如helmet
)也应该尽早执行。 - 使用高效的中间件:对于常见的功能,选择性能较好的中间件。例如,对于日志记录,
morgan
是一个轻量级且高效的日志中间件。
- 精简中间件数量:只使用必要的中间件,避免引入过多不必要的功能。例如,如果应用不需要处理静态文件,就不要引入
- 路由的设计:
- 路由分层:按照功能模块对路由进行分层,例如将用户相关的路由放在
/users
前缀下,订单相关的路由放在/orders
前缀下。这样可以提高代码的可维护性,并且在处理大量路由时,有助于优化路由匹配性能。 - 减少路由嵌套深度:过深的路由嵌套可能导致路由匹配性能下降。尽量保持路由结构扁平,例如
/users/:id/orders
比/users/:id/settings/orders
更优。 - 使用路由参数缓存:对于频繁访问且参数不变的路由,可以考虑缓存响应结果。例如,使用
express - cache - response
中间件,根据路由参数和请求方法缓存响应。
- 路由分层:按照功能模块对路由进行分层,例如将用户相关的路由放在
- 其他方面:
- 启用gzip压缩:使用
compression
中间件对响应数据进行gzip压缩,减少网络传输的数据量,提高响应速度。
const compression = require('compression'); app.use(compression());
- 优化数据库查询:在Express应用与数据库交互时,确保数据库查询是高效的。使用合适的索引,避免全表扫描,并且合理控制数据库连接池的大小,以避免资源浪费。
- 使用CDN:对于静态资源(如CSS、JavaScript、图片等),使用CDN(内容分发网络)来加速资源的加载。可以将静态资源上传到CDN服务提供商,然后在HTML中引用CDN链接。
- 启用gzip压缩:使用