nodejs中错误优先模式和承诺的替代方案?

时间:2016-06-30 09:54:40

标签: node.js error-handling

在nodejs中,当您使用错误优先模式调用异步函数时,即使您无法在当前函数级别处理错误并且只想将其传输到上一个函数,您也可以写这个:

var myAsyncFunc = function (callback) {
    doStuff();
    doAsyncStuff(function (err, res) {
        if (err) {
            callback(err);
            return;
        }
        res = doSomeOtherStuff(res);
        callback(null, res);
    });
};

4行" if(err)..."是那里说"我不能在这里处理错误,所以我只是传播它"。 对我来说,这看起来并不是处理错误的优雅方式。就像在同步代码中我必须这样做:

void mySyncFunc() {
    doStuff();
    try {
        int res = doSyncStuff();
        return doSomeOtherSuff(res);
    } catch (SomeException e) {
        throw e;
    }
}

这太可怕了,我很高兴能够写下来:

void mySuncFunc() throws SomeException {
    doStuff();
    int res = doSyncStuff();
    return doSomeOtherStuff(res);
}

在有人说之前,async.series不会改变这个问题(它只允许更少的嵌套,但你仍然需要做if(错误)部分。)

Promises允许编写更紧凑和优雅的代码。但它们仍然为语言添加了一个很大的层,大多数nodejs模块都不会使用它们。

我的问题是:

  • 不使用承诺& es6,是否有另一种模式而不是错误 - 首先编写更紧凑的代码(我想不是,因为我已经搜索了很多...但我想确定)
  • 为什么有这么多代码使用这种杂乱的方式来传播错误;似乎没有人觉得这很累,即使经过多年使用同步语言这么容易?我完全错过了一个重点吗?

1 个答案:

答案 0 :(得分:1)

反应性扩展

我可以想到一个替代方案,你还没有提到:Reactive Extensions。但就像promises一样,它为回调添加了一层抽象,让你可以在运营商链的末尾处理错误:

var observedAsyncFunc = Rx.Observable.fromCallback(asyncFunc); 

这将返回一个函数,您可以运行该函数并可选地将参数放入(asyncFunc期望的那样)

var source = observedAsyncFunc(); //this "runs" the asyncFunc (/returns the observable)

现在开始“运行”(在这个例子中,结果只是自身乘以):

source
    .map(result => result * result)
    //...

...最后,当你完成操作时,订阅observable,你可以在那里对结果采取行动并处理错误:

source
    .map(result => result * result)
    .subscribe(
        result => console.log("we got something "+result),
        error => console.log("ERROR"),
        () => console.log("observable completed")
    );

<强>承诺

我知道你写过,你不想听到任何关于任何承诺废话的事情,但你也写过你有很多节点模块没有实现承诺的问题。这实际上并不是一个问题,因为(鉴于节点模块中的异步函数符合标准回调模式),您可以promisify()函数使其返回一个promise。例如,如果您使用Bluebird,则可以:

var Promise = require('bluebird');
var promisifiedAsyncFunc = Promise.promisify(asyncFunc);

promisifiedAsyncFunc()
    .then(function(res){/*...*/})
    .catch(function(err){/*...*/});