2015-10-19 21 views
5

In Node.js, come si concatenano insieme i metodi di classe, quando è consigliabile utilizzare i callback?Metodi di concatenamento con callback?

Nei miei giorni di PHP, vorrei tipicamente fare qualcosa di simile:

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(); 

Questo approccio OO molto comune che si permesso di metodi di concatenare le volte che si voleva.

Quando si lavora con Node.js, si può ancora eseguire in qualche modo il concatenamento in questo modo? O finisci semplicemente nel callback dell'inferno? Ogni singola "catena" è una callback annidata?

Oppure ho semplicemente bisogno di avvolgere il mio script in Promises?

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

È così che dovresti farlo? C'è un modo per integrare questo più profondamente nella mia classe in modo da non doverlo avvolgere in promesse ogni volta? Ho visto che alcune librerie hanno una sorta di "modalità promessa" come https://github.com/sindresorhus/got ma dopo aver visto il codice non sono ancora sicuro di come l'hanno fatto.

+0

è questo quello che stai cercando? https://github.com/kriskowal/q e https://www.npmjs.com/package/q –

+0

Bene, non utilizzare una libreria Promise con Node 4.x, giusto? –

+0

Suppongo che forse ho solo bisogno di restituire nuove promesse in ogni metodo e che mi permette di concatenarle usando '.then'. È giusto? –

risposta

4

Si catena utilizzando return this per le chiamate sincrone.

Si catena utilizzando Promise o callback per le chiamate asincrone.

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

Interessante, quindi è una combinazione del 2. Ci scherzo con questo. Grazie –

+0

È possibile concatenare, ad esempio: 'myObject.set (...). Save(). Set (...)' in qualche modo? Sto cercando di capire un modo per collegare QUALSIASI metodo della mia classe a un altro, come in PHP. Non sono sicuro che sia possibile. –

+0

PHP non è multi-thread o su un ciclo di eventi, quindi non devi preoccuparti di * metodi asincroni * come JavaScript. Questo è un inconveniente di PHP, dal momento che si possono sprecare risorse durante l'attesa. Dovrai usare "Promises" o una libreria "async'-like per gestire le cose. – TbWill4321

0

È possibile memorizzare uno speciale variabile membro privata __lastPromise. Inizialmente verrà risolto per impostazione predefinita. Ma poi qualsiasi funzione che esegue un'attività lo aggiornerà con una promessa di ritorno. E anche la funzione stessa eseguirà il proprio compito solo dopoprecedente promessa memorizzata.

Ti piace questa:

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; 
} 

classe Completa:

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

Consiglio vivamente di non utilizzare questo approccio a meno che non sia necessario sequenziare tutte le operazioni. – Bergi

Problemi correlati