You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express服务器同步编程是否阻塞访客?异步代码改写是否正确?

你的两个问题我来逐一解答:

一、同步读取文件对多访客的影响

Node.js是单线程事件循环模型,同步的fs.readFileSync()会阻塞整个事件循环——这意味着在那3秒的读取过程中,服务器完全无法处理任何其他请求,包括访客B的请求。

举个实际场景的例子:

  • 访客A在0秒发起请求,触发3秒的同步读取,此时事件循环被彻底卡住
  • 访客B在第1秒发起请求,这个请求会被放到请求队列里排队等待
  • 直到第3秒同步读取完成,事件循环恢复运转,服务器才会开始处理访客B的请求

所以访客B不需要等5秒,他的实际等待时间是从发起请求到同步操作结束的时长(也就是2秒),之后处理请求是瞬间完成的。但核心问题是:同步操作会让服务器在这段时间内彻底无法响应任何其他请求,这对有一定并发量的服务来说是非常致命的,所以你改成异步的思路完全正确。

二、你改写的异步代码存在的漏洞

你的改写方向没问题,但有一个关键隐患:服务器启动后,fs.readFile()是异步执行的,在回调函数触发前,locationList是undefined。如果这时候有访客访问,res.render()会把undefined传给模板,大概率会导致页面渲染出错,甚至抛出异常。

给你两种靠谱的修正方案:

方案1:确保数据加载完成后再启动服务器

把服务器启动的逻辑放到fs.readFile的回调里,这样只有当数据加载完成后,服务器才开始接收请求,从根源避免未初始化的问题:

const express = require('express');
const fs = require('fs');
const app = express();
let locationList;

fs.readFile('locationList.json', (err, data) => {
  if (err) {
    console.error('加载位置数据失败:', err);
    process.exit(1); // 加载失败直接退出,避免服务异常运行
  }
  locationList = JSON.parse(data);
  
  // 数据加载完成后再注册路由、启动服务器
  app.get('/', function(req, res, next) {
    res.render('index', { locationList: locationList });
  });

  app.listen(3000, () => {
    console.log('服务器已启动,监听端口3000');
  });
});

方案2:在路由中处理未加载完成的情况

如果不想阻塞服务器启动(比如需要先启动其他接口),可以在路由里判断locationList是否已初始化,未初始化时返回友好提示:

const express = require('express');
const fs = require('fs');
const router = express.Router();
let locationList;
let isDataLoaded = false;

fs.readFile('locationList.json', (err, data) => {
  if (err) {
    console.error('加载位置数据失败:', err);
    return;
  }
  locationList = JSON.parse(data);
  isDataLoaded = true;
});

router.get('/', function(req, res, next) {
  if (!isDataLoaded) {
    return res.status(503).send('服务器正在初始化,请稍后再试');
  }
  res.render('index', { locationList: locationList });
});

module.exports = router;

另外,考虑到你提到有单独脚本定期刷新数据,后续如果需要重新加载locationList,也记得用异步的fs.readFile(),还可以加个简单的锁机制,避免同时触发多次文件读取操作。


内容的提问来源于stack exchange,提问作者Fabian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:39:43