1

I have a very basic migration code that looks like this. It removes the table, creates the table, and seeds it with some data.

this.knex.schema.dropTable(this.tableName)
.catch((err) => console.log(err))
.then(() => {
    this.knex.schema.createTable(this.tableName, function(table) {
        table.increments("id").primary();
        table.string("name");
        table.integer("parent_id").unsigned().default(0);
    })
    .catch((err) => console.log(err))
    .then(() => {
        this.categories.forEach((category) => {
            Category.create(category)
            .catch((err) => console.log(err))
            .then((category) => console.log(category.get("name") + " seeded."))
        });
    });
});

As you may notice, there is 3x .catch((err) => console.log(err)) chain on the code.

Right now I have Bugsnag integrated to my application and I want to make sure I properly log all the exceptions/errors on Bugsnag so I can fix all the bugs. However, right now all I can do is to log them into console. Even worse, I repeat myself and duplicating the logic in each catch block.

I'm thinking about doing something like this:

.catch((err) => ErrorHandler.add(err))

class ErrorHandler {

    add(err) {
        // Notify Bugsnag
        // Log it to console
    }

}

That abrings another issue. What if I forget adding catch methods... then it still won't work.

Thought about doing something like this, too:

// Change exception behaviour so whenever they are called, they raise an  `onException` event
app.listen("onException", (err) => {
    // Notify Bugsnag
    // Log error to console
});

this way I can catch all errors and DRY my code, but I'm not sure if Node supports hooking exceptions.

What would you do in my case and what kind of approach should I take? I want to make sure all errors are properly sent to Bugsnag.

4

1 回答 1

1

首先,是否this.knex.schema.createTable返回一个承诺?(如果不是,您总是可以将其转换为返回承诺)如果是这样,您可以以更简洁的方式编写此逻辑,例如:

this.knex.schema.dropTable(this.tableName)
.then((...) => {
  ...
  return this.knex.schema.createTable(...)
})
.then((...) => {
 ... // do whatever you are doing with table object
  return Promise.all( map and do whatever you are doing with categories)
})
.then(() => {
  // log that everything went well with seeding
})
.catch((err) => {
  // single catch block to handle errors from this promise chain
})

Promise.all如果数组中的任何承诺被拒绝,将返回被拒绝的承诺,如果您发现这不符合您的需求,您可以.reflect()从 bluebird 使用(节点中本机承诺支持没有的东西,http://bluebirdjs.com/docs/api/reflect .html )

其次,您可以考虑使用诸如 bunyan 之类的东西,而不是 console.log(console.error 或其他),https://github.com/trentm/node-bunyan

第三,一般来说,你总是需要保护你的应用程序免受攻击uncaughtException,比如

process.on('uncaughtException', (err) => {
  ...
}) 

如果我忘记添加 catch 方法怎么办

从我的角度来看,这将是代码中的错误,您需要意识到这一点。就像您忘记在回调中处理错误一样,例如:

doSomething((err, data) => {
  // do something with data without checking against err
})

所以可以问同样的问题,What if I forget to check against err简单地说,你没有处理错误。根据经验,不要只测试晴天场景,就像一切顺利一样。针对您的代码中的不同场景进行测试,包括某些东西会抛出的雨天场景,确保您以正确的方式处理它。

Express您在问题中提到,您还可以从中受益的另一件事。您可以注册需要在所有路由之后定义的全局错误处理程序,例如:

app.use((err, req, res, next) => {
  ...
})

有了这个,您可以从任何路线将您的错误传递return next(err)给这个处理程序(如果不需要一些特殊的错误处理逻辑,特定于特定的端点),确保您可以从一个地方处理您的错误,例如日志错误并返回500一些消息什么的。https://expressjs.com/en/guide/error-handling.html

于 2016-08-18T13:04:07.140 回答