【问题标题】:Why does NodeJS* event loop continues after my Promise?为什么 NodeJS* 事件循环在我的 Promise 之后继续?
【发布时间】:2020-08-12 02:51:08
【问题描述】:

问题

如何让 NodeJS 只继续事件循环,直到解析完所有参数?

信息

根据thisthis 的回答,我得到Promise 的工作,所以当--password 用于我正在开发的应用程序中时。现在它等待用户输入并且不会立即继续 NodeJS 事件循环。

if (argv.password || argv.w) {
  const p = new Promise((res) => {
    read({ prompt: 'Password: ', silent: true }, function(er, password) {
      console.log('Your password is: %s', password);
      res(password);
    })
  });
  p.then((pw) => console.log(pw));
}

上面的效果很好,但是当我添加时

if (argv.update || argv.u) {
  console.log('Not suppose to see this yet')
  cUpdate(argv.input, config, proj, argv.username, password)
}

然后也执行这段代码,这不是我想要的。

如果我将上述内容内联

if (argv.password || argv.w) {
  const p = new Promise((res) => {
    read({ prompt: 'Password: ', silent: true }, function(er, password) {

      // NEW CODE ADDED HERE
      if (argv.update || argv.u) {
        cUpdate(argv.input, config, proj, argv.username, password)
      }

      res(password);
    })
  });
  p.then((pw) => console.log(pw));
}

然后我从cUpdate() 收到此错误

(node:9005) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:9005) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

【问题讨论】:

    标签: javascript node.js ecmascript-6


    【解决方案1】:

    原因是处理程序中某处出现错误,我什至怀疑承诺不在您的代码中,而是在您调用的 read 方法中。

    为了避免这种情况,请让您的 Promise 处理程序代码尽可能简单,并尽可能使用 then 链:

    if (argv.password || argv.w) {
      const p = new Promise((res) => {
        read({ prompt: 'Password: ', silent: true }, function(er, password) {
          res(password);
        })
      });
      p.then((password) => {
        console.log(password); 
        if (argv.update || argv.u)
          cUpdate(argv.input, config, proj, argv.username, password);
      });
    }
    

    现在我假设 cUpdate 方法失败(看起来不像是这种情况),所以我们需要一些错误处理 - 首先在实际提示和 cUpdate 周围。

    if (argv.password || argv.w) {
      const p = new Promise((res, rej) => {
        read({ prompt: 'Password: ', silent: true }, function(er, password) {
          if (er) rej(er);
          else res(password);
        })
      });
    
      p.then((password) => {
        console.log(password); 
        if (argv.update || argv.u)
          cUpdate(argv.input, config, proj, argv.username, password);
      })
      .catch(e => console.error(e));
    }
    

    现在您可能会在此处看到错误,例如缺少 configproj 条目。

    我还假设错误可能来自 cUpdate 方法内部,并且它也可能是异步的,但是由于您没有尝试在任何地方捕获错误并且您没有处理它显示的承诺那里的警告。幸运的是,then 方法允许您返回另一个 Promise,它也会被处理。我还会像这样使用promisify 简化读取处理程序:

    const _read = require("util").promisify(read);
    
    if (argv.password || argv.w) {
      _read({ prompt: 'Password: ', silent: true }) // this will essentially handle the error and resolve with the password
        .then(password => {
          console.log(password); 
          if (argv.update || argv.u)
            // all you need it to return the output of the method here if it's a promise.
            return cUpdate(argv.input, config, proj, argv.username, password);
        })
        .catch(e => {
          console.error(e);
          process.exit(10); // this will allow you to see an error in the command line
        });
    }
    

    【讨论】:

    • 您认为最后两个代码 sn-ps 中哪个是最佳实践?
    • @SandraSchlichting 绝对是promisify 的最后一个。您也可以稍微调整一下,以便.then 回调中的if 在外部(因此,只有在设置了argv.update 时,您才使用cUpdate 执行then
    【解决方案2】:

    你需要处理你的错误:

    如果发生错误,实现拒绝处理程序。

    if (argv.password || argv.w) {
          const p = new Promise((res, rej) => {
            read({ prompt: 'Password: ', silent: true }, function(er, password) {
    
              // NEW CODE ADDED HERE
              if (er) rej(er)
              if (argv.update || argv.u) {
                cUpdate(argv.input, config, proj, argv.username, password)
              }
    
              res(password);
            })
          });
          p.then((pw) => console.log(pw)).catch(err=> console.log(err))
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-08
      • 2014-06-20
      • 2020-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      • 2022-12-03
      相关资源
      最近更新 更多