首页 > 解决方案 > 在节点中挂起承诺

问题描述

我有一个 Node.js CLI 应用程序,它动态导入 chokidar(取决于传递的标志),并执行一个返回 a 的函数Promise

// index.ts
options.watch
  ? import('chokidar').then(({ default: chokidar }) =>
      chokidar
        .watch(options.watch)
        .on('ready', async () => watchAndBuild(options))
        .on('change', async () => watchAndBuild(options))
    )
  : watchAndBuild(options)

Promise返回的watchAndBuild内容如下

// watchAndBuild.ts
return new Promise(resolve => {
  if (options.run) {
    rl.pause()
    const commandToRun = typeof options.run === 'string' ? options.run : `node ${outdir}`
    const [commandName] = commandToRun.split(' ')
    const commandParameters = commandToRun.split(' ').slice(1)
    child = spawn(commandName, commandParameters, { stdio: 'inherit' })
    child.on('close', () => {
      rl.resume()
      options.watch ? resolve() : process.exit()
    })
  } else {
    console.log(
      `${options.entry || options._.join(', ')} built successfully on ${options.outdir}`
    )
    resolve()
  }
})

预计当--watch--run标志都没有通过时,代码会执行它的任务,记录成功消息,解析承诺并自然退出进程(不需要process.exit()),但是,它会挂在resolve(),任何关于什么的线索我做错了吗?

标签: javascriptnode.jstypescript

解决方案


libuv不知何故,这个问题与node中的一些问题有关>=14.6.0,解决方案就像升级 node 版本一样简单,更多细节在这里

而且,我忘记关闭之前创建的readline界面,在修复它之前Promise放一个rl.close()权利resolve()

// watchAndBuild.ts
import readline from 'readline'

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
})

const watchAndBuild = () =>
  new Promise(resolve => {
    if (options.run) {
      rl.pause()
      const commandToRun = typeof options.run === 'string' ? options.run : `node ${outdir}`
      const [commandName] = commandToRun.split(' ')
      const commandParameters = commandToRun.split(' ').slice(1)
      child = spawn(commandName, commandParameters, { stdio: 'inherit' })
      child.on('close', () => {
        rl.resume()
        options.watch ? resolve() : process.exit()
      })
    } else {
      console.log(
        `${options.entry || options._.join(', ')} built successfully on ${options.outdir}`
      )
      rl.close() // <--- Closes the previously declared readline interface
      resolve()
    }
  })

export default watchAndBuild

推荐阅读