2016-06-30 3 views
0

nodejsでは、エラーファーストのパターンを使用して非同期関数を呼び出すと、現在の関数のレベルでエラーを処理できず、それを上位関数に送信したい場合でも、これを記述する必要があります:nodejのエラーファーストパターンと約束の代替案?

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

4行「(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(err)部分を実行する必要があります)。

約束はよりコンパクトで上品なコードを書くことを可能にします。しかし、彼らはまだ言語に大きな層を追加し、nodejsモジュールのほとんどはそれらを使用しません。

私の質問は以下のとおりです。

  • 約束& ES6を使用せずに、よりコンパクトなコードを書くためのエラー-最初よりも別のパターンは、(私はすでに多くのことを検索するので、ないと仮定...しかし、私があります
  • エラーを伝播させるこのクラッタの方法を使用するコードがあまりにも多いのはなぜですか。これが簡単な同期言語を何年も使っていても、誰もこの疲れを感じないようですね。私は本当に重要な点を欠いていますか?

答えて

1

反応性拡張

私は、あなたがすでに言及していないと考えることができます一つの代替があります:Reactive Extensionsが。しかし、多くの約束のように、それはあなたがオペレータチェーンの最後でエラーを処理することができますコールバックに抽象化の層を追加します。

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

これは、あなたが実行して、必要に応じて(ここでパラメータを置くことができる機能を返します

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

を...そして最後に、ときに」:

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

は今、 "動作" を開始)asyncFuncが期待されている(この例では、結果だけで)自身と乗算され、動作して完成し再、あなたはその結果に基づいて行動し、エラーを処理できる場所、観測可能に加入:

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

約束

私はあなたが書いた知っている、あなたはどんな約束については何も聞きたくありませんナンセンスだが、多くのノードモジュールには約束を履行していないという問題があると書いてある。これは実際には問題ではありません(ノードモジュールの非同期関数が標準コールバックパターンに準拠しているため)、promisify()関数を使用して約束を返すことができるからです。たとえば、Bluebirdを使用している場合は、次の操作を実行できます。

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

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

詳細な回答ありがとうございます。 REは興味深いようですが、Promisesと同じ利点があり、ES6では標準ではないように感じます。それを使うのはあまり意味がないかもしれません。ところで、私は約束がナンセンスだとは言いたくありませんでした!本当に良いことがあります。それはES6のような言語でそれらを持つ代わりにlibsでそれらを使用することは大きな問題であり、使用する方法があまりうまくいかないことです。 – Sebastien

+0

あなたは正しいです、Rx observablesは(私が答えで行ったように)約束の機能をシミュレートするのに使うことができます。そうすれば約束どおりに振る舞いますが、それはポイントですか? Observablesはもっと多くのことをすることができますが、それはこの質問の範囲にはありません。言語声明へ:私は、オブザーバブルとは異なることを約束したと思った[ES6の一部](http://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects)。 –