处理promise库

时间:2016-06-23 04:56:17

标签: node.js promise bluebird

Bluebird模块检测到非Error拒绝时,它会报告Warning: a promise was rejected with a non-error

因此,当我们编写一个可重用的promise库时,如果客户端的代码抛出简单的值,我们应该如何处理这种情况呢?

简单my-library示例:

var Promise = require('bluebird');

module.exports = function (cb) {
    return new Promise(function (resolve, reject) {
        try {
            cb();
            resolve('some data');
        } catch (e) {

            // should we do this?
            reject(e);

            // or should we do this?
            // reject(e instanceof Error ? e : new Error(e));
        }
    });
};

消费它的客户:

var lib = require('my-library');

lib(function () {
    throw 'Regular text';
})
    .catch(function (error) {
        // - should we expect exactly 'Regular text' here?
        // - or should it be wrapped into Error by the promise library?
    });

在上面的示例中,我们将再次看到相同的Warning: a promise was rejected with a non-error,在这种情况下显然是客户端的错,但问题是 - 它会报告拒绝的promise库。< / p>

这带来了一个可重用库如何处理这种情况的问题。

  • 选项1:不执行任何操作(只需使用reject(e)),让客户端看到警告消息Warning: a promise was rejected with a non-error

  • 选项2:验证引发的错误是Error的实例,如果不是,请执行reject(new Error(e))。这使得客户端可以使用简单的值抛出和拒绝,这可能很糟糕。

我在这里寻找一般性建议。

还要考虑有时候客户端可能是一个旧的库,你试图将其包含在promises中。

3 个答案:

答案 0 :(得分:2)

你应该明确地,客观地用错误包装非错误。

非错误对于调试非常糟糕,蓝鸟警告就在那里,因为如果它是一个原语,那么非常很难找出错误来自哪里。您不能将属性附加到基元,并且它们没有堆栈跟踪。

堆栈跟踪意味着您不必猜测错误的来源 - 您知道。

也就是说,bluebird已经使用promisifypromisifyAll自动执行此操作并考虑使用它们。如果您手动执行此操作 - 只需确保堆叠的throwreject内容。

节点另外会查找未处理拒绝的堆栈跟踪 - 因此拒绝使用垃圾不仅会在Node中提供无用的信息,而且可能会导致程序崩溃。

答案 1 :(得分:1)

错误消息应包含在错误对象中,但不能自动

自动换行会降低堆栈跟踪的实用性。例如,假设客户端函数为f,库函数为g

function f(x) { throw 'Hello world' }
function g(f, x) { try { f(x); } catch (e) { throw new Error(e); } }

g(f, 1)

发生错误的客户端函数和行号将完全从堆栈中丢失:

Error: Hello world
    at g (repl:1:52)
    at repl:1:1

如果客户端函数创建了错误对象:

function f(x) { throw new Error('Hello world'); }
function g(f, x) { try{ f(x); } catch (e) { throw e; } }

g(f, 1)

我们得到一个完整的堆栈跟踪:

Error: Hello world
    at f (repl:1:23)
    at g (repl:1:25)
    at repl:1:1

无法将堆栈恢复到库中的某个位置,使用户无法使用它们(它们无法调试自己的代码)。

也就是说,这在很大程度上取决于您正在制作什么类型的库以及您希望它向用户呈现的合同类型。在使用用户传递的回调之前,您应该仔细考虑,因为它们会反转堆栈中的正常责任链。

Promise使这更容易,因为它们取消了反转:首先调用库来生成一个promise,然后该promise被传递回调。因此,创建新错误以及创建承诺允许Bluebird至少部分地查看/扩充客户端代码的堆栈(创建承诺的行将出现在堆栈中)。警告仍然存在,因为无法提供完整的堆栈。

答案 2 :(得分:0)

不,他们只是希望您将JSON错误对象包装成某些东西。

这不是自由,也不是自由。

在庞大的错误包装器中包装简单的JSON对象毫无意义。

不要听他们说。