2016-06-30 8 views
0

Wenn Sie in Nodejs eine asynch Funktion aufrufen, die das Error-First-Muster verwendet, müssen Sie dies schreiben, auch wenn Sie den Fehler auf der Ebene der aktuellen Funktion nicht behandeln und nur an die obere übergeben möchten :Alternativen zu Fehler zuerst Muster und Versprechen, in NodeJs?

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

die 4 Zeilen „if (err) ...“, die es zu sagen gibt „kann ich den Fehler hier nicht umgehen, so dass ich es nur propagieren“. Für mich sieht das wirklich nicht elegant aus, um Fehler zu behandeln. Es ist wie wenn in einem synchronen Code, den ich, dies zu tun hatte:

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

Das wäre schrecklich, und ich bin froh, dass nur schreiben:

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

Und bevor jemand sagt es, async.series ändert dieses Problem nicht (es erlaubt nur weniger Verschachtelung, aber Sie müssen immer noch den if (err) -Teil machen).

Versprechen erlauben, kompakteren und eleganteren Code zu schreiben. Aber sie fügen der Sprache immer noch eine große Ebene hinzu, und die meisten Module von nodejs verwenden diese nicht.

Meine Fragen sind:

  • ohne Versprechungen & es6 zu verwenden, gibt es ein anderes Muster als die fehler ersten kompakten Code zu schreiben (ich nehme nicht an, weil ich schon viel gesucht ... aber ich will sicher sein)
  • warum gibt es so viel Code mit diesem Clutter Weg der Ausbreitung des Fehlers; und niemand scheint das ermüdend zu finden, selbst nach Jahren synchronen Sprachen, wo das so einfach ist? Fehle ich überhaupt einen wichtigen Punkt?

Antwort

1

Reactive Extensions

Es gibt eine Alternative, die ich denken kann, nicht wahr bereits erwähnt: Reactive Extensions. Aber ähnlich wie Versprechungen fügt es eine Abstraktionsschicht auf den Rückruf, die Sie Fehler am Ende einer Bedienungskette handhaben lässt:

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

Diese eine Funktion gibt, die Sie ausführen können, und gegebenenfalls setzen Parameter (die erwartet werden durch asyncFunc)

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

beginnen jetzt "in Betrieb" (in diesem Beispiel wird das Ergebnis nur mit sich selbst multipliziert):

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

... und schließlich, wenn Sie‘ Wieder fertigen Betriebs, auf die beobachtbaren abonnieren, in dem Sie auf das Ergebnis wirken können und Fehler behandeln:

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

Promises

Ich weiß, Sie schrieb, wollen Sie nichts über jede Versprechen hören Unsinn, aber du hast auch geschrieben, dass du ein Problem mit vielen Knotenmodulen hast, die Versprechen nicht umsetzen. Das ist eigentlich nicht wirklich ein Problem, denn (da die asynchronen Funktionen im Node-Modul dem Standard-Callback-Muster entsprechen) können Sie die Funktion promisify() die Funktion geben, um eine Zusage zurückzugeben.Wenn Sie zum Beispiel Bluebird verwenden, können Sie:

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

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

Vielen Dank für Ihre ausführliche Antwort. RE scheint interessant zu sein, aber es fühlt sich an, als hätte es dieselben Vorteile wie Promises und ist in ES6 nicht Standard; Es mag also nicht viel Sinn machen, es zu benutzen. Übrigens, ich wollte nicht sagen, dass Versprechungen Unsinn sind! Es gibt wirklich gute. Es ist nur so, dass es ein großes Problem ist, sie mit libs zu verwenden, anstatt sie in der Sprache wie in ES6 zu verwenden, und sie dadurch viel weniger nützlich zu machen. – Sebastien

+0

Sie haben recht, Rx-Observables können verwendet werden, um Versprechensfunktionalität zu simulieren (wie ich es in der Antwort getan habe) und sie verhalten sich sehr ähnlich wie Versprechen, wenn Sie das tun, aber das ist der Punkt, richtig? Observable können viel mehr, aber das ist nicht im Rahmen dieser Frage. Zur Sprachaussage: Ich dachte, dass Versprechungen im Gegensatz zu Observablen [sind Teil von ES6] (http://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects). –