Um dos maiores problemas com o uso de callbacks em operações assíncronas é o conhecido como callback hell . Ele acaba tornando seu código horizontal, dificultando a legibilidade.
Copy façaAlgo(function(resultado) {
façaOutraCoisa(resultado, function(novoResultado) {
façaOutraCoisaDiferente(novoResultado, function(resultadoFinal) {
console.log(`Resultado final: ${resultadoFinal}`);
}, callbackErro);
}, callbackErro);
}, callbackErro);
Para contornar esse (e outros) problema(s) foram idealizadas as Promises que, por meio do chamado chaining , contornam o callback hell.
Copy façaAlgo()
.then(function(resultado) {
return façaOutraCoisa(resultado);
})
.then(function(novoResultado) {
return façaOutraCoisaDiferente(novoResultado)
})
.then(function(resultadoFinal) {
console.log(`Resultado final: ${resultadoFinal}`);
})
.catch(callbackErro);
Mesmo com o exemplo acima sendo pequeno, fica claro o ganho de legibilidade com o uso de chaining em Promises ao invés do callback hell.
Um erro comum é tentar fazer promise chaining adicionando varios .then a uma mesma promise.
Copy const promise = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(1);
}, 1);
});
promise.then(function(resultado) {
console.log(resultado); // 1
return resultado + 1;
});
promise.then(function(resultado) {
console.log(resultado); // 1
return resultado + 1;
});
promise.then(function(resultado) {
console.log(resultado); // 1
return resultado + 1;
});
Como não esta sendo feito o chaining e sim apenas adicionando varios .then() na promise, a execução desses .then() é feita de forma independente.
Tambem é possivel retornar uma promise dentro de outra promise.
Copy new Promise(function(resolve, reject) {
setTimeout(function() {
return resolve(1);
}, 1);
}).then(function(resultado) {
console.log(resultado); // 1
return new Promise(function(resolve, reject) {
return setTimeout(function() {
return resolve(resultado + 1);
}, 1);
});
}).then(function(resultado) {
console.log(resultado); // 2
return new Promise(function (resolve, reject) {
return setTimeout(function() {
return resolve(resultado + 1);
}, 1);
});
}).then(function(resultado) {
console.log(resultado); // 3
});