使用Promise改写递归读取代码时出现Cannot read property 'then' of undefined错误求助
解决TypeError: Cannot read property 'then' of undefined的Promise改写问题
你遇到这个错误的核心原因非常明确:Node.js内置的readline.question()方法并不是Promise风格的API,它只接受回调函数作为参数,并不会返回Promise对象。所以当你直接在rl.question("name: ")后面调用.then()时,实际上是在undefined上调用方法,自然会抛出TypeError。
修复步骤:
首先我们需要把rl.question()封装成一个返回Promise的工具函数,让它能适配Promise链:
// 封装readline.question为Promise function askQuestion(prompt) { return new Promise((resolve) => { rl.question(prompt, (userAnswer) => { resolve(userAnswer); }); }); }
然后修改你的递归函数,使用这个封装后的方法,同时还要处理exit分支的边界情况,避免后续Promise链执行错误:
function recursiveAsyncReadLine(){ askQuestion("name: ") .then((answer)=>{ if(answer === "exit"){ rl.close(); return; // 这里必须return,终止后续Promise链的执行 } const kitty = new Kitten({name : answer}); return kitty.save(); }) .then((kitty)=>{ // 如果是exit分支,kitty会是undefined,需要跳过后续逻辑 if (!kitty) return; kitty.speak(); return Kitten.find(); }) .then((kittens)=>{ if (kittens) console.log(kittens); // 递归调用,继续循环提问 recursiveAsyncReadLine(); }) .catch((err)=>{ // 不要直接throw err,否则会终止整个程序 console.error("操作出错:", err); // 出错后可以选择继续让用户输入,或者根据需求终止 recursiveAsyncReadLine(); }); }
更简洁的async/await写法
如果你的环境支持ES2017+,用async/await可以让代码逻辑更清晰:
async function recursiveAsyncReadLine(){ try { const answer = await askQuestion("name: "); if(answer === "exit"){ rl.close(); return; } const kitty = new Kitten({name : answer}); await kitty.save(); kitty.speak(); const kittens = await Kitten.find(); console.log(kittens); recursiveAsyncReadLine(); } catch(err) { console.error("操作出错:", err); recursiveAsyncReadLine(); } }
关键细节说明
- Promise封装的必要性:传统回调式API无法直接使用Promise链,必须手动把回调逻辑包裹在Promise中,通过
resolve传递异步结果。 - exit分支的return:当用户输入
exit时,关闭readline后必须return,否则后续的.then()会接收到undefined,调用kitty.speak()会引发新的错误。 - 错误处理优化:原代码中直接
throw err会导致程序崩溃,改成捕获错误并提示,同时可以选择继续递归,提升程序的健壮性。
内容的提问来源于stack exchange,提问作者Riddle Aaron
相关产品推荐
相关产品推荐

