Qual é o padrão de disposição do promise?

Eu li sobre o padrão de disposição de promise em vários lugares, mas não consigo descobrir o que é. Foi sugerido para mim usá-lo em código que se parece com:

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

Qual é o padrão de disposição do compromisso e como se aplica aqui?


Nota – em promises nativas, eu shim .finally como “adicionar manipuladores de rejeição e preenchimento que retornam o valor, mas executam uma ação”. Estou usando o bluebird neste caso, se for importante.

O problema com seu código

O problema com a abordagem acima é que, se você esquecer de liberar a conexão depois de cada vez que executar o getDb você terá um vazamento de resources que poderá congelar seu aplicativo eventualmente quando ficar sem o recurso que está vazando.

Você pode, em um só lugar:

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

Que irá vazar uma conexão de database que nunca foi fechada.


O padrão do triturador

O padrão de disposição é uma maneira de acoplar um escopo de código ao proprietário do recurso. Ao vincular o recurso a um escopo, garantimos que seja sempre liberado quando terminarmos e não podemos esquecer de liberá-lo facilmente. É semelhante ao using em C #, with Python e try-with-resource em Java, bem como RAII em C ++.

Parece que:

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

Aplicando aqui

Se escrevemos nosso código como:

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

Poderíamos escrever nosso código acima como:

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

Exemplos de usuários do padrão disposer são sequelize e knex (construtor de consulta do bookshelf). Também é possível usá-lo para coisas mais simples, como ocultar um carregador quando todas as solicitações AJAX forem concluídas, por exemplo.

pássaro azul

Como você está usando o bluebird, ele tem funções .disposer e Promise.using dedicadas que permitem lidar com a liberação / liberação de vários resources ao mesmo tempo que você pode querer considerar.