如何让Inquirer等待函数执行完毕后再发起新提问
问题描述
我用以下代码循环调用Inquirer:
function start() { let stop = 0; const askQuestion = () => { inquirer .prompt([ { type: "list", name: "action", message: "WHAT TO DO?", choices: ["books", "other", "exit"], loop: true, }, ]) .then((answers) => { if (stop == 0) { if (answers.action == "books") { fetchBooks(); } else if (answers.action == "exit") { stop = 1; return; } askQuestion(); } }); }; askQuestion(); } start();
我的fetchBooks函数包含API调用(books数组来自独立JSON文件):
function fetchBooks() { var len = 0; var booksAll = []; books.forEach((book) => { var bookname = APICALL(book.id).then((bxk) => { var b = { name: book.name, short: bxk.text }; booksAll.push(b); len++; if (len === books.length) { console.log(booksAll); } }); }); }
(无需关注fetchBooks的正确性,它本身运行正常)
当前问题:选择“books”时,fetchBooks的执行与Inquirer的新提问同时进行,输出重叠。需要让Inquirer等待fetchBooks执行完毕并输出结果后,再发起新的提问。
解决方案
核心是让fetchBooks返回Promise,通过异步链式调用或async/await,确保它执行完成后再触发下一次提问。
1. 修改fetchBooks,让它返回Promise
方式一:用Promise.all简化多API调用逻辑(推荐)
function fetchBooks() { // 用Promise.all等待所有API调用并行完成 return Promise.all(books.map(book => { return APICALL(book.id).then(bxk => { return { name: book.name, short: bxk.text }; }); })).then(booksAll => { console.log(booksAll); return booksAll; // 可选:返回结果供后续逻辑使用 }); }
方式二:给原有逻辑套Promise外壳
如果不想改动原有的计数逻辑,可以直接用Promise包裹:
function fetchBooks() { return new Promise((resolve) => { var len = 0; var booksAll = []; books.forEach((book) => { APICALL(book.id).then((bxk) => { var b = { name: book.name, short: bxk.text }; booksAll.push(b); len++; if (len === books.length) { console.log(booksAll); resolve(booksAll); // 执行完成后触发resolve } }); }); }); }
2. 修改Inquirer逻辑,等待fetchBooks完成后再提问
方式一:链式调用then
function start() { let stop = 0; const askQuestion = () => { inquirer .prompt([ { type: "list", name: "action", message: "WHAT TO DO?", choices: ["books", "other", "exit"], loop: true, }, ]) .then((answers) => { if (stop == 0) { if (answers.action == "books") { // 等待fetchBooks执行完成后,再发起下一次提问 fetchBooks().then(() => { askQuestion(); }); } else if (answers.action == "exit") { stop = 1; return; } else { // 其他操作直接继续提问 askQuestion(); } } }); }; askQuestion(); } start();
方式二:用async/await简化代码
function start() { let stop = 0; // 把askQuestion改成async函数 const askQuestion = async () => { const answers = await inquirer.prompt([ { type: "list", name: "action", message: "WHAT TO DO?", choices: ["books", "other", "exit"], loop: true, }, ]); if (stop == 0) { if (answers.action == "books") { await fetchBooks(); // 等待fetchBooks完成 askQuestion(); } else if (answers.action == "exit") { stop = 1; return; } else { askQuestion(); } } }; askQuestion(); } start();
内容的提问来源于stack exchange,提问作者M. Uslu
相关产品推荐
相关产品推荐

