ES6 promete callback resolvido?

Eu quero executar a mesma ação se a minha promise foi resolvida com sucesso ou não. Eu não quero ligar a mesma function para ambos os argumentos de. Não existe um. .always como jQuery tem? Se não, como faço para isso?

Não existe um. .always como jQuery tem?

Não, não há (ainda) . Embora haja uma proposta ativa , talvez ES2018.

Se não, como faço para isso?

Você pode implementar o método finally assim:

 Promise.prototype.finally = function(cb) { const res = () => this const fin = () => Promise.resolve(cb()).then(res) return this.then(fin, fin); }; 

ou mais extensivamente, com informações de resolução de passagem para o retorno de chamada:

 Promise.prototype.finally = function(cb) { const res = () => this return this.then(value => Promise.resolve(cb({state:"fulfilled", value})).then(res) , reason => Promise.resolve(cb({state:"rejected", reason})).then(res) ); }; 

Ambos garantem que a resolução original é mantida (quando não há exceção no retorno de chamada) e que as promises são esperadas.

Com async / wait, você pode esperar uma combinação com try/finally , assim:

 async function(somePromise) { try { await somePromise(); } finally { // always run this-- even if `somePromise` threw something } } 

Aqui está um exemplo real que eu tenho rodando em produção com o Node, usando o plugin async-to-generator de Babel.

 // Wrap promisified function in a transaction block export function transaction(func) { return db.sequelize.transaction().then(async t => { Sequelize.cls.set('transaction', t); try { await func(); } finally { await t.rollback(); } }); } 

Eu uso esse código dentro de um teste mocha ao lado do Sequelize ORM para iniciar uma transação de database, e independentemente do resultado das chamadas de database dentro do teste, sempre reverter no final.

Isso é aproximadamente análogo ao método .finally() do Bluebird, mas IMO, syntax muito mais agradável!

( Nota : Caso você esteja se perguntando por que não estou await o primeiro Promise, é um detalhe de implementação do Sequelize. Ele usa o CLS para “vincular” uma transação SQL a uma cadeia Promise. Qualquer coisa que incorra dentro da mesma cadeia Qualquer coisa fora não é.Portanto, aguardando na promise teria ‘fechado’ o bloco de transação e quebrou a cadeia.Eu joguei este exemplo para mostrar-lhe como maneja ‘baunilha’ Promise pode ser misturado ao lado asynchronous funções e jogar bem juntos.)

Se você não / não pode atualizar o protótipo, a maneira de hackar um finalmente é:

 executeMyPromise() .then(function(res){ return {res: res}; }) .catch(function(err){ return {err: err}; }) .then(function(data) { // do finally stuff if (data.err) { throw data.err; } return data.res; }).catch(function(err) { // handle error }); 

Aqui está minha implementação de .finally ().

 Promise.prototype.finally = function(cb) { return this.then(v=>Promise.resolve(cb(v)), v=>Promise.reject(cb(v))); }; 

Eu testei:

 (new Promise((resolve,reject)=>{resolve(5);})).finally(x=>console.log(x)); //5 (new Promise((resolve,reject)=>{reject(6);})).finally(x=>console.log(x)); //6 (new Promise((resolve,reject)=>{reject(7);})) .then(x=>x,y=>y) .catch(x=>{throw "error";}) .finally(x=>{console.log(x); throw "error"; return x;}) // 7 .then(x=>console.log(x),y=>console.log('e')); //e // Uncaught (in promise) undefined 

Não há necessidade de introduzir novos conceitos

 const promise = new Promise((resolve, reject) => { /*some code here*/ }); promise.then(() => { /* execute success code */ }, () => { /* execute failure code here */ }).then(() => {}, () => {}).then(() => { /* finally code here */ }); 

Para estender a resposta Bergi .

Retornar Promise.reject () no manipulador de captura evitará que o finnalizing ‘then’ seja chamado.

Então, se você vai lidar com erros de promise 2 ou mais vezes, deve usar o boilerplate da seguinte maneira:

 return myPromise() .then(() => ... ) .catch((error) => { ... myFinnaly(); return Promise.reject(error); }) .then(() => myFinnaly());