Obtendo Resultados de Promises em JavaScript
Anteriormente, exploramos como, a partir de uma função promise, podemos passar para fora o resultado de uma operação assíncrona:
const myPromise = new Promise(function (resolve) {
console.log("Executando a operação assíncrona");
resolve("Olá mundo!");
});Agora, vamos obter esse valor. Para receber o resultado de uma operação de promise, usamos a função then() do objeto Promise:
then(onFulfilled, onRejected);O primeiro parâmetro da função, onFulfilled, representa a função que é executada quando a promise é resolvida com sucesso e recebe os dados passados em resolve().
O segundo parâmetro, onRejected, representa a função que é executada em caso de erro e recebe os dados passados em reject().
A função then() também retorna um objeto Promise.
Assim, podemos obtemos os dados:
const myPromise = new Promise(function (resolve) {
console.log("Executando a operação assíncrona");
resolve("Olá mundo!");
});
myPromise.then(function (value) {
console.log(`Dados recebidos da promise: ${value}`);
});O parâmetro value aqui representará a string "Olá mundo!", que é passada em resolve("Olá mundo!"). Consequentemente, a saída no console será:
Executando a operação assíncrona Dados recebidos da promise: Olá mundo!
Para exemplificar, vamos chamar várias promises para ver a assincronia em ação:
const myPromise3000 = new Promise(function (resolve) {
console.log("[myPromise3000] Executando a operação assíncrona");
setTimeout(() => {
resolve("[myPromise3000] Olá mundo!");
}, 3000);
});
const myPromise1000 = new Promise(function (resolve) {
console.log("[myPromise1000] Executando a operação assíncrona");
setTimeout(() => {
resolve("[myPromise1000] Olá mundo!");
}, 1000);
});
const myPromise2000 = new Promise(function (resolve) {
console.log("[myPromise2000] Executando a operação assíncrona");
setTimeout(() => {
resolve("[myPromise2000] Olá mundo!");
}, 2000);
});
myPromise3000.then((value) => console.log(value));
myPromise1000.then((value) => console.log(value));
myPromise2000.then((value) => console.log(value));Aqui, definimos três promises idênticas. Cada uma não é executada imediatamente, utilizando a função setTimeout e definindo o valor retornado apenas após alguns segundos. Os tempos de atraso são diferentes para cada promise. Neste caso, a saída no console será:
[myPromise3000] Executando a operação assíncrona [myPromise1000] Executando a operação assíncrona [myPromise2000] Executando a operação assíncrona [myPromise1000] Olá mundo! [myPromise2000] Olá mundo! [myPromise3000] Olá mundo!
Observamos que o primeiro a iniciar foi o myPromise3000, mas ele terminou por último devido ao maior tempo de atraso estabelecido, 3 segundos. No entanto, esse atraso não impediu a execução das outras promises.
Além disso, não é necessário passar um valor em resolve(). A operação assíncrona pode simplesmente ocorrer sem retornar um valor:
const x = 4;
const y = 8;
const myPromise = new Promise(function () {
console.log("Executando a operação assíncrona");
const z = x + y;
console.log(`Resultado da operação: ${z}`);
});
myPromise.then();Neste caso, a função na promise calcula a soma dos números x e y e imprime o resultado no console.
Método Promise.resolve
Às vezes, é necessário simplesmente retornar um valor de uma promise. Para isso, pode-se usar o método Promise.resolve(). Este método recebe o valor a ser retornado pela promise e devolve um objeto Promise:
const myPromise = Promise.resolve("Olá mundo!");
myPromise.then((value) => console.log(value)); // Olá mundo!Definindo uma Promise por Meio de uma Função
Frequentemente, uma promise é definida por uma função que retorna um objeto Promise. Por exemplo:
function sum(x, y) {
return new Promise(function (resolve) {
const result = x + y;
resolve(result);
});
}
sum(3, 5).then(function (value) {
console.log("Resultado da operação:", value);
});
sum(25, 4).then(function (value) {
console.log("Soma dos números:", value);
});A função sum() recebe dois números e retorna uma promise que encapsula a operação de soma desses números. Após o cálculo, a soma é passada para resolve(), e então podemos obter o resultado por meio do método then(). Definir uma promise através de uma função nos permite, por um lado, passar diferentes valores ao chamar a função. Por outro lado, tratamos o resultado dessa função como uma promise e configuramos o tratamento do valor recebido para cada chamada específica.
O resultado:
Resultado da operação: 8 Soma dos números: 29
Mas, e se o princípio de tratamento do valor obtido da função assíncrona for o mesmo?
sum(3, 5).then(function (value) {
console.log("Resultado da operação:", value);
});
sum(25, 4).then(function (value) {
console.log("Resultado da operação:", value);
});Nesse caso, a lógica de tratamento será repetida. Como o método then() também retorna um objeto Promise, podemos proceder da seguinte forma:
function sum(x, y) {
return new Promise(function (resolve) {
const result = x + y;
resolve(result);
}).then(function (value) {
console.log("Resultado da operação:", value);
});
}
sum(3, 5);
sum(25, 4);Configuração Flexível da Função
E se quisermos que o programador tenha a opção de definir seu próprio manipulador, ou, se ele preferir, aplicar um manipulador padrão? Neste caso, podemos definir a função do manipulador como um parâmetro da função e, se não for fornecido, definir um manipulador padrão:
function sum(x, y, func) {
// se não for definido um manipulador, então definimos um manipulador padrão
if (func === undefined)
func = function (value) {
console.log("Resultado da operação:", value);
};
return new Promise(function (resolve) {
const result = x + y;
resolve(result);
}).then(func);
}
sum(3, 5);
sum(25, 4, function (value) {
console.log("Soma:", value);
});Aqui, na primeira chamada da função sum(3, 5), será utilizado o manipulador padrão function(value) { console.log("Resultado da operação:", value); }. No segundo caso, o manipulador é explicitamente passado por meio do terceiro parâmetro, portanto, será usado function(value) { console.log("Soma:", value); }.