Node.js readline 只让我回答我的第一组问题然后无限期挂起。 (附带可重现的样品!)

Node.js readline only lets me answer my first set of questions then hangs indefinitely. (Reproducible sample attached!)

我有这个程序:

  1. 递归查找存储库(参见recurse()
  2. 在每个存储库中,查找我定期更新的特定点文件(参见 update()
  3. 提示用户确认每次更新(参见 confirm()
function confirm(prompt, defaultOption = true) {
    console.warn("At confirm");
    return new Promise(function(resolve, reject) {
        console.warn("Question asked");

        readline.question(prompt, async function(answer) {
            console.warn("Question answered");

            if (/^y(es)?$/i.test(answer) || (answer === "" && defaultOption === true)) {
                resolve(true);
            } else if (/^n(o)?$/i.test(answer) || (answer === "" && defaultOption === false)) {
                resolve(false);
            } else {
                resolve(await confirm(prompt, defaultOption));
            }
        });
    });
}

async function update(directory = baseDirectory) {
    console.warn("At update");

    for (const file of [[".eslintrc.json"], ["tsconfig.json"], [".vscode", "extensions.json"], [".vscode", "settings.json"]]) {
        if (fs.existsSync(path.join(directory, file[file.length - 1]))) {
            console.warn("Before confirm");

            console.log("==== " + directory + " ====");

            if (argv["yes"] === true || (await confirm(directory + "\tOverwrite `" + file[file.length - 1] + "`? [Y/n] ")) === true) {
                fs.copyFileSync(path.join(kerplowDirectory, ...file), path.join(directory, ...file));
            }

            console.warn("After confirm");
        }
    }
}

(function recurse(directory = baseDirectory) {
    for (const file of fs.readdirSync(directory)) {
        if (fs.statSync(path.join(directory, file)).isDirectory()) {
            if (file === ".git") {
                console.warn("Before update");

                update(directory);

                console.warn("After update");
            }

            if (file !== "node_modules") {
                recurse(path.join(directory, file));
            }
        }
    }
})();

问题是双重的:

  1. readline重复问第一个问题
  2. 它只会问第一组问题,然后完全停止响应输入

示例输出:

At update
Before confirm
==== .bash_logout ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== .bashrc ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== .cache ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== .config ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== .npm ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== .profile ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== .upm ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== config.json ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update
Before update
At update
Before confirm
==== index.js ====
At confirm
Question asked
.bash_logout    Overwrite `.eslintrc.json`? [YAfter update

Question answered
After confirm
Before confirm
==== .bash_logout ====
At confirm
Question asked
.bash_logout    Overwrite `tsconfig.json`? [Y/n]
Question answered
After confirm
Before confirm
==== .bash_logout ====
At confirm
Question asked
.bash_logout    Overwrite `extensions.json`? [Y/n]
Question answered
After confirm
Before confirm
==== .bash_logout ====
At confirm
Question asked
.bash_logout    Overwrite `settings.json`? [Y/n]
Question answered
After confirm


<indefinite hang>

回复:

https://repl.it/repls/LuminousRapidNaturaldocs

已尝试修改文件并修复问题。我从repl复制了代码。

有几个问题:

  • 解决后您需要从 readline.question return。正因如此,第一道题在循环
  • recurse 也需要是异步的,以便一次提示一个文件
const fs = require("fs");
const readline = require("readline").createInterface({
  "input": process.stdin,
  "output": process.stdout
});

function confirm(prompt, defaultOption = true) {
    console.warn("At confirm");

    return new Promise(function(resolve, reject) {
        console.warn("Question asked");

        readline.question(prompt, async function(answer) {
            console.warn("Question answered");

            if (/^y(es)?$/i.test(answer) || (answer === "" && defaultOption === true)) {
                resolve(true);
                return
            } else if (/^n(o)?$/i.test(answer) || (answer === "" && defaultOption === false)) {
                resolve(false);
                return
            } else {
                resolve(await confirm(prompt, defaultOption));
            }
        });
    });
}

async function update(directory) {
    console.warn("At update");

    for (const file of [[".eslintrc.json"], ["tsconfig.json"], [".vscode", "extensions.json"], [".vscode", "settings.json"]]) {
    //  if (fs.existsSync(path.join(directory, file[file.length - 1]))) {
            console.warn("Before confirm");

            console.log("==== " + directory + " ====");

            if (/* argv["yes"] === true || */ (await confirm(directory + "\tOverwrite `" + file[file.length - 1] + "`? [Y/n] ")) === true) {
    //          fs.copyFileSync(path.join(kerplowDirectory, ...file), path.join(directory, ...file));
                // break;
            }

            console.warn("After confirm");
    //  }
    }
    // return
}
console.log(fs.readdirSync(process.cwd()));

(async function recurse(directory) {
    for (const file of fs.readdirSync(directory)) {
    //  if (fs.statSync(path.join(directory, file)).isDirectory()) {
    //      if (file === ".git") {
                console.warn("Before update");

                await update(file);

                console.warn("After update");
    //      }

    //      if (file !== "node_modules") {
    //          recurse(path.join(directory, file));
    //      }
    //  }
    }
})(process.cwd());

我现在得到的输出是:

[ '.eslintrc.json', 'id.js', 'index.js', 'tsconfig.json' ]
Before update
At update
Before confirm
==== .eslintrc.json ====
At confirm
Question asked
.eslintrc.json  Overwrite `.eslintrc.json`? [Y/nY <= Screen waits here for Y/N
Question answered
After confirm
Before confirm
==== .eslintrc.json ====
At confirm
Question asked
.eslintrc.json  Overwrite `tsconfig.json`? [Y/nY <= Screen waits here for Y/N
Question answered
After confirm
Before confirm
==== .eslintrc.json ====
At confirm
Question asked
.eslintrc.json  Overwrite `extensions.json`? [Y/nY <= Screen waits here for Y/N
Question answered
After confirm
Before confirm
==== .eslintrc.json ====
At confirm
Question asked
.eslintrc.json  Overwrite `settings.json`? [Y/nY <= Screen waits here for Y/N

And it repeats for other files in the local directory

如果这有帮助,请告诉我。如有任何疑问,请回复。