Qual è lo schema del dissipatore di promise?

Ho letto del pattern del dissipatore di promise in diversi punti ma non riesco a capire di cosa si tratta. Mi è stato suggerito di usarlo in codice che assomiglia a:

function getDb(){ return myDbDriver.getConnection(); } var users = getDb().then(function(conn){ return conn.query("SELECT name FROM users").finally(function(users){ conn.release(); }); }); 

Qual è lo schema del dissipatore di promise e come si applica qui?


Nota: nelle promesse native, spacco .finally come “aggiungi sia i gestori di rifiuto che di esecuzione che restituiscono il valore ma eseguono un’azione”. Sto usando bluebird in questo caso se è importante.

Il problema con il tuo codice

Il problema con l’approccio precedente è che se si dimentica di rilasciare la connessione dopo ogni singola volta che si esegue getDb si ha una perdita di risorse che potrebbe bloccare l’app alla fine quando si esaurisce la risorsa che si perde.

Potresti, in un posto fare:

 var users = getDb().then(function(conn){ return conn.query("SELECT name FROM users"); }); 

Che colerà una connessione al database che non è mai stata chiusa.


Il modello di smaltimento

Il pattern del dissipatore è un modo per accoppiare un ambito di codice con il possesso della risorsa. Legando la risorsa ad un ambito ci assicuriamo che venga sempre rilasciato quando abbiamo finito e non possiamo facilmente dimenticare di rilasciarlo. È simile using in C #, with in Python e try-with-resource in Java e RAII in C ++.

Sembra:

  withResource(function(resource){ return fnThatDoesWorkWithResource(resource); // returns a promise }).then(function(result){ // resource disposed here }); 

Applicandolo qui

Se abbiamo scritto il nostro codice come:

 function withDb(work){ var _db; return myDbDriver.getConnection().then(function(db){ _db = db; // keep reference return work(db); // perform work on db }).finally(function(){ if (_db) _db.release(); }); } 

Potremmo scrivere il nostro codice sopra come:

  withDb(function(conn){ return conn.query("SELECT name FROM users"); }).then(function(users){ // connection released here }); 

Esempi di utenti del pattern del dissipatore sono sequelize e knex (query builder di bookshelf). È anche ansible utilizzarlo per cose più semplici come hide un caricatore quando tutte le richieste AJAX sono state completate, ad esempio.

Bluebird

Dato che stai utilizzando bluebird, ha dedicato funzioni Promise.using e .disposer incorporate che ti consentono di gestire / rilasciare più risorse contemporaneamente che potresti prendere in considerazione.