Bookshelf和async的未处理拒绝错误

时间:2017-09-04 09:26:23

标签: node.js promise async-await bluebird bookshelf.js

在Bookshelf的保存挂钩中抛出错误时,我遇到了未处理拒绝错误的问题。 Bookshelf有一个custom event handler,可以使用事件的Promises,以及一个extended version of Bluebird的Promises。

'use strict'

const knex = require('./src/knex')
const Bookshelf = require('bookshelf')
const bookshelf = Bookshelf(knex)

class MyModel extends bookshelf.Model {
  get tableName () {
    return 'my_table'
  }

  initialize () {
    bookshelf.Model.prototype.initialize.call(this)

    this.on('saving', () => {
      throw new Error('Some validation')
    })
  }
}

async function main () {
  try {
    await bookshelf.transaction(async (trx) => {
      return MyModel
        .forge({
          id: 0,
        })
        .save(null, {
          patch: true,
          transacting: trx,
        })
    })
  } catch (err) {
    console.log(err)
  }
}

main()

这是输出:

knex:tx trx1: Starting top level transaction +0ms
Unhandled rejection Error: Some validation
  at MyModel.on (/test.js:18:13)
  at /node_modules/bookshelf/lib/base/events.js:176:25
From previous event:
  at MyModel.triggerThen (/node_modules/bookshelf/lib/base/events.js:175:32)
  at MyModel.<anonymous> (/node_modules/bookshelf/lib/model.js:1045:19)
From previous event:
  at MyModel.<anonymous> (/node_modules/bookshelf/lib/model.js:970:8)
From previous event:
  at bookshelf.transaction (/test.js:30:10)
  at /node_modules/knex/lib/transaction.js:81:20
  at runCallback (timers.js:781:20)
  at tryOnImmediate (timers.js:743:5)
  at processImmediate [as _immediateCallback] (timers.js:714:5)
From previous event:
  at /node_modules/knex/lib/transaction.js:75:10
  at runCallback (timers.js:781:20)
  at tryOnImmediate (timers.js:743:5)
From previous event:
  at new Transaction (/node_modules/knex/lib/transaction.js:68:41)
  at Client_PG.transaction (/node_modules/knex/lib/client.js:158:12)
  at Object.transaction (/node_modules/knex/lib/util/make-knex.js:75:21)
  at Object.transaction (/node_modules/bookshelf/lib/bookshelf.js:247:36)
  at main (/test.js:25:21)
  at Object.<anonymous> (/test.js:40:1)
  at Module._compile (module.js:573:30)
  at Object.Module._extensions..js (module.js:584:10)
  at Module.load (module.js:507:32)
  at tryModuleLoad (module.js:470:12)
  at Function.Module._load (module.js:462:3)
  at Function.Module.runMain (module.js:609:10)
  at startup (bootstrap_node.js:158:16)
  at bootstrap_node.js:598:3

knex:tx trx1: releasing connection +55ms
Error: Some validation
  at MyModel.on (/test.js:18:13)
  at /node_modules/bookshelf/lib/base/events.js:176:25
From previous event:
  at MyModel.triggerThen (/node_modules/bookshelf/lib/base/events.js:175:32)
  at MyModel.<anonymous> (/node_modules/bookshelf/lib/model.js:1045:19)
From previous event:
  at MyModel.<anonymous> (/node_modules/bookshelf/lib/model.js:970:8)
From previous event:
  at bookshelf.transaction (/test.js:30:10)
  at /node_modules/knex/lib/transaction.js:81:20
  at runCallback (timers.js:781:20)
  at tryOnImmediate (timers.js:743:5)
  at processImmediate [as _immediateCallback] (timers.js:714:5)
From previous event:
  at /node_modules/knex/lib/transaction.js:75:10
  at runCallback (timers.js:781:20)
  at tryOnImmediate (timers.js:743:5)
From previous event:
  at new Transaction (/node_modules/knex/lib/transaction.js:68:41)
  at Client_PG.transaction (/node_modules/knex/lib/client.js:158:12)
  at Object.transaction (/node_modules/knex/lib/util/make-knex.js:75:21)
  at Object.transaction (/node_modules/bookshelf/lib/bookshelf.js:247:36)
  at main (/test.js:25:21)
  at Object.<anonymous> (/test.js:40:1)
  at Module._compile (module.js:573:30)
  at Object.Module._extensions..js (module.js:584:10)
  at Module.load (module.js:507:32)
  at tryModuleLoad (module.js:470:12)
  at Function.Module._load (module.js:462:3)
  at Function.Module.runMain (module.js:609:10)
  at startup (bootstrap_node.js:158:16)
  at bootstrap_node.js:598:3

当我从async移除await bookshelf.transaction(async (trx) => {时,错误消失。我知道这里的异步是不必要的,但我很好奇为什么这会导致拒绝被处理?

修改1

我没有在没有Bookshelf的情况下复制错误。

async function main () {
  try {
    await test1()
  } catch (err) {
    console.log(err)
  }
}

async function test1 () {
  return Promise.resolve().then(() => {
    throw new Error('Some validation')
  })
}

main()

这不会产生未处理的拒绝。

修改2

async function main () {
  try {
    await test2()
  } catch (err) {
    console.log(err)
  }
}

async function test2 () {
  return Promise.map([
    (() => {
      throw new Error('Some validation')
    })()
  ])
}

这不会产生未处理的拒绝。

0 个答案:

没有答案