Home > OS >  How to wait function to finish before asking new question with inquirer
How to wait function to finish before asking new question with inquirer

Time:10-04

I'm looping inquirer like:

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();

This works, but my fetchBooks function makes an api call: (books array that I used in foreach is a separate json file)

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);
      }
    });
  });
}

(Please don't mind the correctness of the fetchbooks function, I've polished it to share here, normally it works pretty fine, my problem is not with that)

The thing is, right now this code works.

But when I pick "books" from inquirer, inquirer doesn't wait for asking the question again before I do something with the results from my first answer, fetchBooks execute with the same time of new question from inquirer. So they overlap.

How can I make inquirer to wait before fetchBooks() returns something to screen and then it asks in the new line?

CodePudding user response:

Maybe try this

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().then(() => askQuestion());
          } else if (answers.action == "exit") {
            stop = 1;
            return;
          }
          
        }
      });
  };
  askQuestion();
}

start();
function fetchBooks() {
    var len = 0;
    var booksAll = [];
    return Promise((resolve, reject) => {
        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);
                    resolve()
                }
            });
        });
    });
}

CodePudding user response:

As the commenters have said, async-await is your friend here. If you rewrite your function to use async and await, all the logic becomes simpler:

async function askQuestion() {
  const answers = await inquirer
    .prompt([
      {
        type: "list",
        name: "action",
        message: "WHAT TO DO?",
        choices: ["books", "other", "exit"],
        loop: true,
      }
    ]);

  if (answerrs.action === "books") {
    await fetchBooks();
    askQuestion();
  }
}
  • Related