【问题标题】:Unhandled promise rejection warning returning null未处理的承诺拒绝警告返回 null
【发布时间】:2018-04-12 06:30:29
【问题描述】:

我似乎有一个未处理的承诺拒绝,我找不到...

我已经使用--trace-warnings 运行 nodejs,并且我的脚本顶部有以下代码:

process.on('unhandledRejection', (reason, p) => {
  console.log('Unhandled Rejection at:', p, 'reason:', reason);
  console.log(p)
  console.log(reason)
});

当 promise 被拒绝时,我看到了:

Unhandled Rejection at: Promise { <rejected> null } reason: null
Promise { <rejected> null }
null

我检查了我拥有的几个异步函数和承诺,它们都有.catch() 的...这里到底发生了什么?我怎样才能知道拒绝的来源?

一些代码。我的班级中有以下异步函数:

async loop() {
    console.log("starting loop")
    if ( this.state != this.STOPPED ) {
        switch (this.case) {
            case this.POLLING:
                console.log("Start polling")
                await Promise.all(this.symbols.map(symbol => {
                    return this.fetch(symbol)
                })).then(() => {
                    ...
                }).catch(error => {
                    ...
                })
                for (let symbol of this.symbols) {
                    await this.process(symbol).then(() => {
                        ...                         
                    }).catch(error => {
                        ...
                    })
                } //for
                for (let openPosition of this.openPositions) {
                    this.log.push(openPosition.toLogString())
                }
                console.log("end polling")
                break
        } //state selection case
        console.log(this.log.formatTimestamp(Date.now()))
        this.log.dump()
        this.log.clear()
        console.log("done dumping")
        setTimeout(this.loop.bind(this), 0)
    }
}

奇怪的是输出,它重复:

starting loop
Start polling
end polling
done dumping
Unhandled Rejection at: Promise { <rejected> null } reason: null
Promise { <rejected> null }
null

警告基本上显示在 setTimeout() 打电话。不知道为什么这是一个问题。另外值得注意的是,根据数组this.OpenPositions 中有多少元素,我似乎得到了不同数量的承诺拒绝。对于 n>1,我得到 n-1 个错误,其中 n 是元素的数量。

【问题讨论】:

  • 你可能写了一个你可能没有正确处理错误响应的承诺。你能添加一些代码吗?
  • 您能详细说明一下吗?我不能只发布每个异步函数或承诺,但如果有特定的东西我可以发布块。
  • 控制台或终端中必须有一个行号指示错误
  • 嗯,你需要缩小哪个承诺有未处理的拒绝。我希望当您显示此错误并将其缩小到那些时,您可以弄清楚操作中涉及哪些承诺。您也可以暂时或永久切换到Bluebird promise library,这更有可能为您提供未处理拒绝的堆栈跟踪。
  • 任何地方都没有行号,因此是我的问题。如果我去掉process.on(),它会给我一个类似的消息,没有行号。 nodejs 通常会给我一个未处理的承诺拒绝的跟踪,所以我不确定这里发生了什么。弹出此警告时正在执行的 case 语句有一个 Promise.all(),它有一个 .catch(),还有一个 await function(),它也有一个。

标签: javascript node.js


【解决方案1】:

我不知道这是问题所在,但这似乎是少数几种可能性之一。

async 函数返回一个承诺,这意味着您的 loop() 函数返回一个承诺。如果此函数内部存在不属于其他承诺的错误,则这些错误将变成未处理的拒绝。考虑:

let obj = {
    count: 0,
    async loop() {
      this.count++
        console.log("running: ", this.count)
      if (this.count == 2) throw ("whoops")
      if (this.count < 2) {
        setTimeout(this.loop.bind(this), 0)
    } 
  }
}
obj.loop()

throw() 将导致未处理的 Promise 拒绝,即使函数中没有 Promise。 (我认为sn-p会吞掉它们,但你可以在控制台中看到)

要捕获这些,您需要在 loop() 本身上添加一个 catch。在超时时调用它的方式可能不太方便,但您可以执行以下操作:

let obj = {
  count: 0,
  async loop() {
    this.count++
      console.log("running: ", this.count)
    if (this.count == 2) throw ("whoops")
    if (this.count < 2) {
      if (this.count < 2) {
        setTimeout(() => this.loop()
        .catch(err => console.log("caught error: ", err)), 0)
      }
    }
    return this.count
  }

}
obj.loop().catch(err => console.log("caught error outside: ", err))

【讨论】:

  • (function() { ... }).bind(this)可以简化为() =&gt; { ... }
  • 我怀疑你是对的!谢谢!让我们看看会发生什么
  • @Mark_M re:我调用循环的方式......这似乎是最“javascript-y”的方式。有没有更好的办法?我以为我不能使用 while 循环,因为脚本还在后台运行 nodejs 网络服务器,所以它不能阻塞
猜你喜欢
  • 2020-01-01
  • 2018-07-02
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多