同步代码中似乎没有 运行 异步函数

async function doesn't seem to run inside sync code

我试图创建一个连接到数据库的命令,我创建了一个小的 CLI 脚本,循环遍历特定文件夹中的文件以获取命令 class 模块

我的问题是,在我的一个命令中,我试图连接到 sequelize,但它似乎什么也没做。我没有得到控制台的输出,它甚至似乎也没有尝试连接

这可能是因为我仍然在努力弄清楚如何正确地执行同步/异步/等待...注意我如何使用 glob.sync 因为我想同步循环文件,但是在我的命令中,我需要使用 await

连接到数据库

cli.js:

#! /usr/bin/env node

const patterns = [
    './node_modules/unity/src/commands/**/*.js',
    './src/commands/**/*.js',
]
const glob = require('glob')
const path = require('path')
const yargs = require('yargs')
const signature = yargs.argv._[0]
const process = require('process')

patterns.forEach(pattern => {
    glob.sync(pattern).forEach(file => {
        const commandPath = path.resolve(file)
        const command = require(commandPath)

        if (command.signature == signature) {
            command.argv = yargs.argv
            command.run()

            process.exit()
        }
    })
})

console.log('Command not found.')

这是 commands 文件夹之一中的示例命令:

const { Sequelize } = require('sequelize')

class MigrateCommand {
    static signature = 'migrate'
    static argv = {}

    static run() {
        const sequelize = new Sequelize({
            dialect: 'mysql',
            host: 'localhost',
            port: 3306,
            database: 'dio_unity2',
            username: 'root',
            password: '',
        })

        const connect = async () => {
            try {
                await sequelize.authenticate()
                console.log('Connection successful.')
            }
            catch (error) {
                console.error('Unable to connect.', error)
            }
        }

        connect()

        console.log('migrate run complete')
    }
}

module.exports = MigrateCommand

我已经设置了 npx,所以我可以 运行 npx unity migrate 它会根据 migrate 签名

调用这个命令

现在我的控制台应该显示 connection successfulunable to connect,然后是 migrate run complete,但我在控制台中看到的只是 migrate run complete。就好像它根本就没有尝试连接...

我不知道我做错了什么。

You can't make an asynchronous process synchronous without spawning a new thread and synchronously waiting on it. (There's an npm package that does that, via execSync.)

但这里的好消息是 您的代码中没有必要。您想串联做事,但是串联做事与同步[=]不完全一样42=]。方法如下:

首先,run 无法使它通过 authenticate 同步启动的异步进程。因此,run 应该只是 async(我们不需要 connect):

static async run() {
    const sequelize = new Sequelize({
        dialect: 'mysql',
        host: 'localhost',
        port: 3306,
        database: 'dio_unity2',
        username: 'root',
        password: '',
    })

    try {
        await sequelize.authenticate()
        console.log('Connection successful.')
    } catch (error) {
        console.error('Unable to connect.', error)
    }

    console.log('migrate run complete')
}

接下来,在脚本中,我们使用 async 函数遍历您的模式和文件:

(async () => {
    for (const pattern of patterns) {
        for (const file of glob.sync(pattern)) {
            const commandPath = path.resolve(file)
            const command = require(commandPath)

            if (command.signature == signature) {
                command.argv = yargs.argv
                await command.run() // *** Note the `await`
                process.exit()
            }
        }
    }
    console.log("Command not found.")
})();

那是异步工作,但一个接一个(串联)。


如果是我,我不会使用 process.exit() 来终止进程,这是一种非常激进的进程终止形式,可能会阻止某些事情完成 (details here),并且可能对于以后进行代码维护的人来说不像其他选择那样清楚。现在我们已经将代码放在包装函数中,我只是 return 退出函数来打破循环:

await command.run();
return;