2015-10-19 7 views
5

In Node.js, wie ketten Sie Klassenmethoden zusammen, wenn es am besten ist, Callbacks zu verwenden?Methoden der Kettenklasse mit Callbacks?

In meinen PHP Tagen, ich würde in der Regel etwas tun, wie folgen aus:

class MyClass { 

    function get() { 
    // fetch some data from an API endpoint 
    return this; 
    } 

    function set(property, value) { 
    // Set the property to some value on the object 
    return this; 
    } 

    function save() { 
    // Save the data to database 
    return this; 
    } 
} 

$myObject = new MyClass(); 
$myObject->set('something','taco')->save(); 

Dieses sehr gemeinsames Konzept OO SieFormal Kette Methoden zusammen, so oft erlaubt, wie man wollte.

Können Sie bei der Arbeit mit Node.js immer noch eine ähnliche Verkettung durchführen? Oder enden Sie einfach in der Callback-Hölle? Jede einzelne "Kette" ist ein verschachtelter Rückruf?

Oder muss ich einfach mein Skript in Promises?

new Promise(function(resolve, reject){ 
    var myObject = new MyClass(); 
    myObject.set('something','taco'); 
    resolve(myObject); 
}).then(function(myObject){ 
    myObject.save(); 
}); 

Soll das so sein? Gibt es eine Möglichkeit, dies tiefer in meine Klasse zu integrieren, sodass ich sie nicht jedes Mal in Versprechen einbinden muss? Ich habe einige Bibliotheken gesehen, die eine Art "Versprechensmodus" wie https://github.com/sindresorhus/got haben, aber nachdem ich mir den Code angesehen habe, bin ich mir immer noch nicht ganz sicher, wie sie das gemacht haben.

+0

ist es das, was Sie suchen? https://github.com/kriskowal/q und https://www.npmjs.com/package/q –

+0

Nun, ich verwende keine Promise-Bibliothek mit Knoten 4.x richtig? –

+0

Ich denke, vielleicht muss ich nur neue Promises in jeder Methode zurückgeben und das erlaubt mir, sie mit '.then' zu verketten. Ist das richtig? –

Antwort

4

Sie verketten mit return this für synchrone Anrufe.

Sie verketten mit Promise oder Rückrufe für asynchrone Anrufe.

class MyClass { 
 
    
 
    get() { 
 
    return new Promise((resolve, reject)=> { 
 
     // Make Request and call resolve(result) or reject(err) 
 
    }); 
 
    } 
 
    
 
    set(property, value) { 
 
    this[property] = value; 
 
    return this; 
 
    } 
 
    
 
    save() { 
 
    return new Promise((resolve, reject)=> { 
 
     // Make Request and call resolve(result) or reject(err) 
 
    }); 
 
    } 
 
} 
 

 
var myObject = new MyClass(); 
 

 
myObject 
 
    .set('something', 'taco') 
 
    .save() 
 
    // resolve handler 
 
    .then((saveResult)=> { 
 
    console.log(saveResult); 
 
    return myObject.get(); 
 
    }) 
 
    // resolve handler 
 
    .then((getResult)=> { 
 
    console.log(getResult); 
 
    }) 
 
    // reject handler 
 
    .catch((error)=> { });

+0

Interessant, so ist es eine Kombination der 2. Ich werde damit herumspielen. Danke –

+0

Ist es möglich zu ketten, zum Beispiel: 'myObject.set (...). Save(). Set (...)' irgendwie? Ich versuche einen Weg zu finden, wie ich jede Methode meiner Klasse mit einer anderen verbinden kann, wie Sie es in PHP können. Ich bin mir nicht sicher, ob es möglich ist. –

+0

PHP ist nicht multi-threaded oder in einer Event-Schleife, so dass Sie sich keine Gedanken über * asynchrone * Methoden wie JavaScript machen müssen. Das ist ein Nachteil von PHP, da Sie beim Warten Ressourcen verschwenden können. Sie müssen 'Promises' oder eine' async'-ähnliche Bibliothek verwenden, um mit den Dingen umzugehen. – TbWill4321

0

können Sie speichern eine spezielle private Variable __lastPromise. Anfangs wird es standardmäßig aufgelöst. Aber dann wird jede Funktion, die eine Aufgabe erledigt, sie mit einer Rückgabeversprechung aktualisieren. Und auch die Funktion selbst wird nur ihre Aufgabe tun nach die vorherige Versprechen gespeichert wurde gelöst.

So:

save() { 
     // only after __lastPromise has resolved 
    var newPromise = __lastPromise.then(function() { 
     // Do stuff here 
    }); 

    // update __lastPromise with the newly returned promise 
    this.__lastPromise = newPromise; 

    // return this for regular chaining 
    return this; 
} 

komplette Klasse:

class MyClass { 
    constructor(){ 
     this.__lastPromise = Promise.resolve(); 
     this.a = 0; 
    } 
    set(property, value) { 
     var self = this; 
     self.__lastPromise = self.__lastPromise.then(function() { 
      return new Promise(function(resolve, reject) { 
       console.log('self.%s set to: ', property, value); 
       self[property] = value; 
       resolve(); 
      }); 
     }); 
     return self; 
    } 
    save() { 
     var self = this; 
     self.__lastPromise = self.__lastPromise.then(function() { 
      return new Promise(function(resolve, reject) { 
       console.log('Saved'); 
       resolve(); 
      }); 
     }); 
     return self; 
    } 
} 
var myObject = new MyClass(); 
myObject.set('a', '1').save().set('a', '2').save(); 
this.a set to: 1 
Saved 
this.a set to: 2 
Saved 
+0

Ich würde wirklich empfehlen, diesen Ansatz nicht zu verwenden, wenn Sie nicht alle Ihre Operationen abfolgen müssen. – Bergi