Inquirer.js icon indicating copy to clipboard operation
Inquirer.js copied to clipboard

Using async functions of `fs-extra` as validation will occur unexpected behaviors

Open Alive-Fish opened this issue 3 years ago • 1 comments

As shown as below, if I use async functions like fs.pathExists, it will ask to press enter twice to answer the question3. Also, if ask three questions together (as the comment line), it will occur the issue as the screenshot. image

// inquirer@^8.2.4
import fs from "fs-extra";
import inquirer from "inquirer";

(async () => {
  const question1 = {
    type: "input",
    name: "input",
    validate: async (input: string) => {
      await fs.pathExists("doc.json");
      return true;
    },
  };
  const question2 = {
    type: "list",
    name: "list1",
    choices: ["choice1", "choice2", "choice3"],
  };
  const question3 = {
    type: "list",
    name: "list2",
    choices: ["choice1", "choice2", "choice3"],
  };
  // await inquirer.prompt([question1, question2, question3]); // this works as expectation
  await inquirer.prompt([question1]);
  await inquirer.prompt([question2]);
  await inquirer.prompt([question3]);
})();

Alive-Fish avatar Jul 11 '22 05:07 Alive-Fish

This affects not just the functions of fs-extra, but any async function in either the validate or filter fields. Using this setup you can easily recreate the bug.

const prompt = inquirer.prompt;

// has async function in validate or filter
const one = await prompt([{
    type: "input",
    name: "one",
    message: "prompt 1",
    validate: async inp => {
        await sleep(1000);
        return true;
    }
}]);
// no abnormal behaviour
const two = await prompt([{
    type: "input",
    name: "two",
    message: "prompt 2"
}]);
// requires enter press before text can be input
const three = await prompt([{
    type: "input",
    name: "three",
    message: "prompt 3"
}]);

function sleep (ms) {
    return new Promise(res => setTimeout(res, ms);
}

This will produce the following output after pressing a, [ENTER], b [ENTER], c [ENTER]

? prompt 1 a
? prompt 2 b
? prompt 3 c

And after pressing a, [ENTER], b, [ENTER], c, [ENTER], d, the output will be

? prompt 1 a
? prompt 2 b
? prompt 3 c
? prompt 3 d

After all the prompt have been answered, all answers will be light blue, except for the 'c'.

The bug persists, no matter whether you use async/await, Promises, or this.async()

/**
 * All of these cause the bug if used as validators
 */
async function validateAsync (inp) {
    await sleep(1000);
    return true;
}

function validatePromise (inp) {
    return new Promise(res => setTimeout(res, 1000, true));
}

function validateAsyncCall(inp) {
    const resolve = this.async();
    sleep(1000).then(_ => resolve(true));
}

Console: cmd.exe, Windows Platform: Windows Inquirer: v9.1.0

Mahakadema avatar Sep 07 '22 15:09 Mahakadema

@SBoudrias hey, does this have been fixed? It takes many confuses to our CLI's UI.

Alive-Fish avatar Aug 14 '23 06:08 Alive-Fish

Hey, this is coming from an old version of Inquirer. Would you mind updating to latest #1214; it's very likely to fix this problem, and you'll have a much smaller bundle.

SBoudrias avatar Aug 14 '23 20:08 SBoudrias

Thank you. I will have a try.

Alive-Fish avatar Aug 15 '23 01:08 Alive-Fish