Criando Cadeias de Promises - JavaScript
Uma das vantagens dos promises é a possibilidade de criar cadeias de promises. Anteriormente, vimos a aplicação dos métodos then()
catch()
Promise
then()
catch()
promise.then(..).then(..).then(..)
O valor retornado da função manipuladora no método then()
then()
const helloPromise = new Promise(function(resolve) {
resolve("Hello");
});
const worldPromise = helloPromise.then(function(value) {
// retornando um novo valor
return value + " World";
});
const programicioPromise = worldPromise.then(function(value) {
// retornando um novo valor
return value + " from Programício";
});
programicioPromise.then(function(finalValue) {
// obtendo o valor final
console.log(finalValue); // Hello World from Programício
});
Aqui, para maior clareza, todo o processo foi dividido em promises separadas: helloPromise
worldPromise
programicioPromise
Vamos examinar cada etapa.
Primeiro, é criado o promise helloPromise
const helloPromise = new Promise(function(resolve) {
resolve("Hello");
});
Na operação assíncrona, por meio da chamada resolve("Hello")
fulfilled
Em seguida, o método then()
helloPromise
const worldPromise = helloPromise.then(function(value) {
// retornando um novo valor
return value + " World";
});
Como valor do parâmetro value
then()
helloPromise.then()
worldPromise
Em seguida, de maneira semelhante, o método then()
worldPromise
const programicioPromise = programicioPromise.then(function(value) {
// retornando um novo valor
return value + " from Programício";
});
Como valor do parâmetro value
worldPromise.then()
programicioPromise
Na última etapa, o método then()
programicioPromise
programicioPromise.then(function(finalValue) {
console.log(finalValue); // Hello World from Programício
});
Aqui, por meio do parâmetro finalValue
Para maior concisão e clareza, podemos simplificar a cadeia:
new Promise(resolve => resolve("Hello"))
.then(value => value + " World")
.then(value => value + " from Programício")
.then(finalValue => console.log(finalValue));
Tratamento de Erros
Para tratar erros, adicionamos o método catch()
Promise
function generateNumber(str) {
return new Promise((resolve, reject) => {
const parsed = parseInt(str);
if (isNaN(parsed)) reject("Not a number");
else resolve(parsed);
});
}
function printNumber(str) {
generateNumber(str)
.then(value => console.log(value))
.catch(error => console.log(error));
}
printNumber("hello"); // Not a number
printNumber("3"); // 3
Neste caso, a função generateNumber()
printNumber()
then()
catch()
Se a conversão da string para número no promise for bem-sucedida, o número convertido é passado para a função resolve()
else resolve(parsed)
Neste caso, ao receber este resultado, o método then()
.then(value => console.log(value))
O método catch()
No entanto, se o valor passado não puder ser convertido em número, o seguinte é executado no promise:
if (isNaN(parsed)) reject("Not a number");
Neste caso, o método then()
.catch(error => console.log(error));
Tratando Erros na Cadeia de Promises
Agora vamos complicar a cadeia. Suponha que vários promises sejam executados consecutivamente:
function generateNumber(str) {
return new Promise((resolve, reject) => {
const parsed = parseInt(str);
if (isNaN(parsed)) reject("Not a number");
else resolve(parsed);
});
}
function printNumber(str) {
generateNumber(str)
.then(value => {
if (value === 4) throw "Número azarado";
return value * value;
})
.then(finalValue => console.log(`Result: ${finalValue}`))
.catch(error => console.error(error));
}
printNumber("rty"); // Not a number
printNumber("3"); // Result: 9
printNumber("4"); // Número azarado
printNumber("5"); // Result: 25
Aqui, para simplificar, todo o código está na função generateNumber()
catch()
throw()
reject()
then()
catch()
Por exemplo, ao chamar a função printNumber() com diferentes dados de entrada:
printNumber("rty");
Recebemos a mensagem "Not a number" no console, pois a string "rty" não pode ser convertida em um número.
Retornando um Promise de catch
Vale ressaltar que, como catch()
Promise
function generateNumber(str) {
return new Promise((resolve, reject) => {
const parsed = parseInt(str);
if (isNaN(parsed)) reject("Not a number");
else resolve(parsed);
});
}
function printNumber(str) {
generateNumber(str)
.then(value => value * value)
.then(value => console.log(`Result: ${value}`))
.catch(error => console.error(error))
.then(() => console.log("Work has been done"));
}
printNumber("3");
// Result: 9
// Work has been done
O método then()
catch()
catch()
Além disso, podemos passar um valor da função manipuladora de erros no catch()
then()
function generateNumber(str) {
return new Promise((resolve, reject) => {
const parsed = parseInt(str);
if (isNaN(parsed)) reject("Not a number");
else resolve(parsed);
});
}
function printNumber(str) {
generateNumber(str)
.then(value => value * value)
.then(value => console.log(`Result: ${value}`))
.catch(error => {
console.log(error);
return 0;
})
.then(value => console.log("Status code:", value));
}
printNumber("ert3"); // Not a number
// Status code: 0
Método finally
Além dos métodos then()
catch()
Promise
finally()
O método finally()
function generateNumber(str) {
return new Promise((resolve, reject) => {
const parsed = parseInt(str);
if (isNaN(parsed)) reject("Not a number");
else resolve(parsed);
});
}
function printNumber(str) {
generateNumber(str)
.then(value => console.log(value))
.catch(error => console.log(error))
.finally(() => console.log("End"));
}
printNumber("3");
printNumber("hi");
Aqui, chamamos duas vezes o promise retornado pela função generateNumber. Em um caso, a string é convertida com sucesso em um número, e no outro, ocorre um erro. No entanto, independentemente da ausência ou presença de erro, o método finally()
O método finally()
function generateNumber(str) {
return new Promise((resolve, reject) => {
const parsed = parseInt(str);
if (isNaN(parsed)) reject("Not a number");
else resolve(parsed);
});
}
function printNumber(str) {
generateNumber(str)
.then(value => console.log(value))
.catch(error => console.log(error))
.finally(() => console.log("Execução do promise concluída"))
.then(() => console.log("O promise ainda está funcionando"));
}
printNumber("3");
Saída no console:
3 Execução do promise concluída O promise ainda está funcionando
Vale destacar que é possível passar dados para o método then
finally
finally()
then()
catch()
function generateNumber(str) {
return new Promise((resolve, reject) => {
const parsed = parseInt(str);
if (isNaN(parsed)) reject("Not a number");
else resolve(parsed);
});
}
function printNumber(str) {
generateNumber(str)
.then(value => {
console.log(value);
return "hello from then";
})
.catch(error => {
console.log(error);
return "hello from catch";
})
.finally(() => {
console.log("End");
return "hello from finally";
})
.then(message => console.log(message));
}
printNumber("3");
Saída no console:
3 End hello from then