Promise.prototype.finally
Promise.prototype.finally
permite registrar um callback para ser chamado quando uma promessa é resolvida (ou seja, concluída com sucesso ou rejeitada).
Imagine que você deseja buscar alguns dados para mostrar na página. Ah, e você quer mostrar um indicador de carregamento quando a requisição começar e ocultá-lo quando a requisição for concluída. Quando algo der errado, você exibe uma mensagem de erro no lugar.
const fetchAndDisplay = ({ url, element }) => {
showLoadingSpinner();
fetch(url)
.then((response) => response.text())
.then((text) => {
element.textContent = text;
hideLoadingSpinner();
})
.catch((error) => {
element.textContent = error.message;
hideLoadingSpinner();
});
};
<!--truncate-->
fetchAndDisplay({
url: someUrl,
element: document.querySelector('#output')
});
Se a requisição for bem-sucedida, exibimos os dados. Se algo der errado, exibimos uma mensagem de erro no lugar.
De qualquer maneira, precisamos chamar hideLoadingSpinner()
. Até agora, não temos outra opção senão duplicar esta chamada tanto no bloco then()
quanto no bloco catch()
. Com Promise.prototype.finally
, podemos fazer melhor:
const fetchAndDisplay = ({ url, element }) => {
showLoadingSpinner();
fetch(url)
.then((response) => response.text())
.then((text) => {
element.textContent = text;
})
.catch((error) => {
element.textContent = error.message;
})
.finally(() => {
hideLoadingSpinner();
});
};
Isso não apenas reduz a duplicação de código, como também separa mais claramente a fase de manipulação de sucesso/erro da fase de limpeza. Muito bom!
Atualmente, a mesma coisa é possível com async
/await
, e sem Promise.prototype.finally
:
const fetchAndDisplay = async ({ url, element }) => {
showLoadingSpinner();
try {
const response = await fetch(url);
const text = await response.text();
element.textContent = text;
} catch (error) {
element.textContent = error.message;
} finally {
hideLoadingSpinner();
}
};
Como async
e await
são estritamente melhores, nossa recomendação continua sendo usá-los em vez de promises padrão. Dito isso, se por algum motivo você prefere promises padrão, Promise.prototype.finally
pode ajudar a tornar seu código mais simples e organizado.