面试题答案
一键面试HTTP缓存策略
- 设置Cache - Control头:
- 在Express应用中,可以通过
res.set('Cache - Control', 'public, max - age = 31536000')
设置响应头。public
表示响应可以被任何中间节点(如浏览器、CDN等)缓存,max - age
设置缓存的有效时间为31536000秒(一年)。这适用于不经常变化的静态资源,如CSS、JavaScript文件等。 - 对于动态生成但变化不频繁的数据,可以设置
Cache - Control: s - maxage = 3600, stale - while - revalidate = 600
。s - maxage
用于共享缓存(如CDN)设置缓存时间为3600秒,stale - while - revalidate
表示在缓存过期后,仍可以使用过期的缓存内容600秒,同时后台去重新验证和更新数据。
- 在Express应用中,可以通过
- ETag头:
- 使用
express - etag
中间件,它会自动为响应生成ETag头。例如:
const express = require('express'); const etag = require('express - etag'); const app = express(); app.use(etag()); app.get('/data', (req, res) => { const data = { message: 'Some data' }; res.json(data); });
- 手动计算ETag,比如对于一个JSON响应数据,可以这样计算:
const crypto = require('crypto'); app.get('/data', (req, res) => { const data = { message: 'Some data' }; const jsonData = JSON.stringify(data); const etagValue = crypto.createHash('sha256').update(jsonData).digest('hex'); res.set('ETag', etagValue); res.json(data); });
- 客户端再次请求时,如果ETag没有变化,服务器可以返回304 Not Modified状态码,减少数据传输。
- 使用
内存缓存策略
- 使用
node - cache
库:- 安装:
npm install node - cache
- 使用示例:
const NodeCache = require('node - cache'); const myCache = new NodeCache(); const express = require('express'); const app = express(); app.get('/cachedData', (req, res) => { const cacheKey = 'cachedDataKey'; const cachedData = myCache.get(cacheKey); if (cachedData) { return res.json(cachedData); } const newData = { message: 'Fresh data' }; myCache.set(cacheKey, newData); res.json(newData); });
- 可以设置缓存过期时间,如
myCache.set(cacheKey, newData, 60)
,这里60表示60秒后缓存过期。
- 安装:
- 基于
Map
对象手动实现简单缓存:const express = require('express'); const app = express(); const cache = new Map(); app.get('/cachedValue', (req, res) => { const key = 'cachedValueKey'; if (cache.has(key)) { const cachedValue = cache.get(key); return res.json(cachedValue); } const newValue = { result: 'New value' }; cache.set(key, newValue); res.json(newValue); });
- 可以添加逻辑来定期清理缓存,比如使用
setInterval
,模拟缓存过期机制:
const express = require('express'); const app = express(); const cache = new Map(); const cacheDuration = 60 * 1000; // 60 seconds setInterval(() => { const now = Date.now(); cache.forEach((value, key, map) => { if (now - value.timestamp > cacheDuration) { map.delete(key); } }); }, cacheDuration); app.get('/cachedValue', (req, res) => { const key = 'cachedValueKey'; if (cache.has(key)) { const cachedValue = cache.get(key).value; return res.json(cachedValue); } const newValue = { result: 'New value' }; cache.set(key, { value: newValue, timestamp: Date.now() }); res.json(newValue); });
- 可以添加逻辑来定期清理缓存,比如使用
异步处理优化
- 使用
async/await
:- 对于数据库查询,假设使用
mysql2
库:
const express = require('express'); const mysql = require('mysql2'); const app = express(); const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'test' }); app.get('/users', async (req, res) => { try { const [rows] = await connection.promise().query('SELECT * FROM users'); res.json(rows); } catch (error) { console.error(error); res.status(500).send('Error fetching data'); } });
- 对于文件读取操作,使用
fs/promises
:
const express = require('express'); const fs = require('fs/promises'); const app = express(); app.get('/fileContent', async (req, res) => { try { const content = await fs.readFile('test.txt', 'utf8'); res.send(content); } catch (error) { console.error(error); res.status(500).send('Error reading file'); } });
- 对于数据库查询,假设使用
- 使用
Promise.all
:- 当需要并行执行多个异步操作,比如同时获取多个API的数据:
const express = require('express'); const axios = require('axios'); const app = express(); app.get('/combinedData', async (req, res) => { const api1Promise = axios.get('https://api.example.com/data1'); const api2Promise = axios.get('https://api.example.com/data2'); try { const [response1, response2] = await Promise.all([api1Promise, api2Promise]); const combinedData = { data1: response1.data, data2: response2.data }; res.json(combinedData); } catch (error) { console.error(error); res.status(500).send('Error fetching data'); } });