Node.js中根据用户输入动态调用函数的优化方案咨询
优化方案推荐
针对你需要动态管理函数映射的需求,这里提供几个实用的优化方案,避免手动维护Map和选项列表:
方案一:统一对象存储(最简方案)
把所有周期函数集中存放在一个对象中,自动从对象的键生成选项列表,新增函数只需在对象中添加,无需修改其他代码:
// 统一存放所有周期处理函数 const periodFunctions = { async Annually() { console.log("Annually works."); }, async Weekly() { console.log("Weekly works."); }, async Daily() { console.log("Daily works."); }, // 新增函数直接追加到这里即可 async Monthly() { console.log("Monthly works."); } }; async function choice() { const answer = await inquirer.prompt({ name: "choice", type: "list", message: "How often do you want to get a notification?", choices: Object.keys(periodFunctions) // 自动生成选项列表 }); // 直接通过键名调用对应函数 await periodFunctions[answer.choice](); }
方案二:装饰器自动注册(灵活扩展)
使用ES装饰器标记需要注册的函数,自动将函数添加到映射中,新增函数只需添加装饰器,无需手动维护映射关系:
注意:需要Node.js启用--experimental-decorators flag,或通过Babel配置支持装饰器语法。
const periodFunctions = new Map(); // 定义装饰器,用于自动注册函数 function Period(optionName) { return function(target, propertyKey) { periodFunctions.set(optionName, target[propertyKey]); }; } class NotificationHandlers { @Period("Annually") static async annually() { console.log("Annually works."); } @Period("Weekly") static async weekly() { console.log("Weekly works."); } @Period("Daily") static async daily() { console.log("Daily works."); } // 新增函数只需添加@Period装饰器并指定选项名称 @Period("Monthly") static async monthly() { console.log("Monthly works."); } } async function choice() { const answer = await inquirer.prompt({ name: "choice", type: "list", message: "How often do you want to get a notification?", choices: Array.from(periodFunctions.keys()) // 自动生成选项 }); await periodFunctions.get(answer.choice)(); }
方案三:自动扫描模块文件(大型项目适配)
如果项目规模较大,函数分散在不同文件中,可以通过Node.js的文件系统API自动扫描指定目录下的模块,实现完全无侵入的函数注册:
目录结构
your-project/ ├── handlers/ │ ├── Annually.js │ ├── Daily.js │ ├── Weekly.js │ └── Monthly.js └── main.js
单个处理函数文件(如Annually.js)
module.exports = async function() { console.log("Annually works."); };
主文件(main.js)
const fs = require('fs').promises; const path = require('path'); const periodFunctions = new Map(); // 自动加载handlers目录下的所有处理函数 async function loadHandlers() { const handlerDir = path.join(__dirname, 'handlers'); const files = await fs.readdir(handlerDir); for (const file of files) { if (file.endsWith('.js')) { const optionName = path.basename(file, '.js'); const handler = require(path.join(handlerDir, file)); periodFunctions.set(optionName, handler); } } } async function choice() { await loadHandlers(); // 先加载所有函数 const answer = await inquirer.prompt({ name: "choice", type: "list", message: "How often do you want to get a notification?", choices: Array.from(periodFunctions.keys()) }); await periodFunctions.get(answer.choice)(); }
方案选择建议
- 小型项目或快速迭代场景:优先选方案一,代码简洁易维护。
- 需要灵活分类或标记函数:选方案二,装饰器语义清晰。
- 大型项目、函数数量多且分散:选方案三,实现完全解耦的动态扩展。
内容的提问来源于stack exchange,提问作者Enes
相关产品推荐
相关产品推荐

