【问题标题】:async function doesn't seem to run inside sync code异步函数似乎没有在同步代码中运行
【发布时间】:2022-02-10 17:37:52
【问题描述】:

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

我的问题是,在我的一个命令中,我正在尝试连接到 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。就好像它根本没有尝试连接......

我不知道我在这里做错了什么。

【问题讨论】:

  • 这与How do I return the result of an asynchronous call? 密切相关,但我们可以在回答这个特定问题方面做得更好,而不是将其作为副本关闭,因为 OP 实际上不需要使代码同步.
  • 为什么你在一次成功运行后会process.exit()?这将忽略除第一个文件之外的所有文件...?
  • @T.J.Crowder 因为如果通过签名找到命令,那么我们知道这是要运行的命令,因此我们不需要检查任何其他命令。跨度>
  • 知道了。我以为你想一次只做一个,而不仅仅是你找到的第一个。
  • 是的,我基本上只是想遍历目录中的所有文件,一旦找到具有特定签名的类,就不需要继续遍历文件。希望这是有道理的。对 JS 世界来说还是很新的东西。

标签: javascript node.js async-await


【解决方案1】:

You can't make an asynchronous process synchronous 无需生成新线程并同步等待它。 (有一个 npm 包可以做到这一点,通过 execSync。)

但这里的好消息是没有必要在您的代码中。您希望按顺序进行,但按顺序进行同步 完全不一样。方法如下:

首先,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),而且人们可能不太清楚稍后进行代码维护作为替代方案。现在我们已将代码放入包装函数中,我只需退出函数以打破循环:

await command.run();
return;

【讨论】:

  • 注意到 OP 声明“我的命令之一....”,暗示只有一个具有异步性,提及 await command.run() 运行完全正常可能很有用,无论 command.run是否异步
  • @Bravo 从类的 run 函数中删除 async 不起作用。然而,TJ 的回答非常有效。
  • @kjdion84 - Bravo 并没有这么建议。他们指出如果你有一个不是asyncrun,那么await command.run()仍然可以。
  • @kjdion84 - 根据您的问题,我了解到您只有一个异步“命令”,这意味着其他命令没有 - 我指出 await 对那些.. . 我的评论中没有任何部分暗示你可以删除await - 也许你已经知道await 是这样工作的(虽然不太可能),我为其他面临类似问题的人发表了评论
  • @Bravo 哦,明白了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多