为何Node.js代码未等待动态模块导入完成?
问题根源与解决方案:异步IIFE未阻塞后续代码执行
问题本质
你的async立即执行函数(IIFE)是异步非阻塞的:JS引擎执行到这个IIFE时,会启动内部的异步模块导入操作,但不会暂停整个代码的执行流程,而是直接继续往下运行创建Express实例、打印SECOND、启动服务器的逻辑。等异步导入完成后,才会回头执行IIFE里await之后的代码,这就是输出顺序混乱的核心原因。
另外还有两个隐藏问题:
- IIFE内部的
webpack和webpackDevMiddleware是局部变量,后续代码根本访问不到,就算顺序正确也没法使用这些模块。 - 代码里
typeof Webpack用了大写变量名,但实际定义的是小写webpack,会导致打印undefined(你提供的输出结果应该是笔误)。
修复方案
方案1:将所有逻辑封装到async启动函数
把服务器初始化的全部逻辑放进一个async函数里,利用await阻塞后续代码执行,确保模块导入完成后再执行后续逻辑:
import express from 'express'; async function startServer() { // 提前声明变量,让后续代码能访问到 let webpack, webpackDevMiddleware; const PORT = 8080; if (process.env.NODE_ENV === 'development') { try { console.log(`About to import`); // 动态导入并赋值给外部变量 const { default: wp } = await import('webpack'); const { default: wpDevMiddleware } = await import('webpack-dev-middleware'); webpack = wp; webpackDevMiddleware = wpDevMiddleware; console.log(`FIRST: typeof webpack ${typeof webpack} | typeof webpackdevmiddleware ${typeof webpackDevMiddleware}`); } catch (error) { console.error('开发环境依赖导入失败:', error); process.exit(1); // 导入失败直接退出服务 } } const server = express(); if (process.env.NODE_ENV === 'development') { console.log(`SECOND: I must run after FIRST`); // 这里可以正常使用webpack和webpackDevMiddleware // 示例:配置webpack-dev-middleware // const compiler = webpack(yourWebpackConfig); // server.use(webpackDevMiddleware(compiler)); } server.listen(PORT, () => { console.log(`Server is listening on port ${PORT}`); }); } // 启动服务器并处理全局错误 startServer().catch(err => console.error('服务器启动失败:', err));
方案2:使用顶层await(Node.js 14.8+支持)
如果你的Node.js版本支持顶层await(v14.8及以上),可以直接在模块顶层使用await,这样会阻塞模块加载,直到异步操作完成:
import express from 'express'; let webpack, webpackDevMiddleware; const PORT = 8080; if (process.env.NODE_ENV === 'development') { try { console.log(`About to import`); const { default: wp } = await import('webpack'); const { default: wpDevMiddleware } = await import('webpack-dev-middleware'); webpack = wp; webpackDevMiddleware = wpDevMiddleware; console.log(`FIRST: typeof webpack ${typeof webpack} | typeof webpackdevmiddleware ${typeof webpackDevMiddleware}`); } catch (error) { console.error('开发环境依赖导入失败:', error); process.exit(1); } } const server = express(); if (process.env.NODE_ENV === 'development') { console.log(`SECOND: I must run after FIRST`); } server.listen(PORT, () => { console.log(`Server is listening on port ${PORT}`); });
验证效果
修复后运行代码,输出顺序会符合预期:
About to import
FIRST: typeof webpack function | typeof webpackdevmiddleware function
SECOND: I must run after FIRST
Server is listening on port 8080
内容的提问来源于stack exchange,提问作者volume one
相关产品推荐
相关产品推荐

