terça-feira, junho 09, 2026

Um Bug Curioso em um Código JavaScript

Embora não seja a minha especialidade, estou dando manutenção em uma aplicação web desenvolvida com Angular (e, portanto, com código em TypeScript). Por estes dias apareceu um bug que acho curioso o suficiente para fazer este post.

Reduzindo o código ao mínimo, temos uma rotina chamada quando um botão na tela é pressionado. Esta rotina precisa chamar duas APIs externas e exibir a mensagem "Aguarde" enquanto aguarda as respostas. No código abaixo, a variável "aguarde" controla a exibição da mensagem (pela magia do Angular).

O código acima funcionava (aparentemente) até que uma mudança de implementação tornou a API 2 muito demorada. Foi aí que se percebeu que o "Aguarde" era retirado antes da hora.


Para entender o que acontece, é preciso saber que o código acima não roda sequencialmente, de cima para baixo. Os métodos chamaApi1 e chamaApi2 retornam "promises", que é a forma moderna de programar JavaScript de forma assíncrona. Ao executar a chamaApi1 e chamaApi2, a execução é suspensa até a chamada ser concluída (quando a "promise" é resolvida); neste ponto são executadas as rotinas associadas a then, catch e finally. Usando cores para indicar o que é executado quando:

A parte destacada em amarelo é executada primeiro. Quando a primeira "promise" é resolvida, serão executados os trechos em azul. O trecho em verde é executado quando a segunda chamada a API é concluída.

O resultado é que o finally() é executado quando a chamada à primeira API é concluída, enquanto a segunda  chamada ainda está em execução.

Se você quiser ver isso no seu navegador, pressione F12 (ou a combinação de teclas que abre as Ferramentas do Desenvolvedor), selecione Console, copie o texto abaixo e pressione Enter para executar.

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const teste = () => {
  console.log('Inicio');
  delay(1000)
  .then (() => {
    console.log('Terminou delay 1');
    delay(2000)
    .then(() => {
      console.log('Terminou delay 2');
    })
    .finally(() => {
      console.log('Finally 2');
    })
  })
  .finally(() => {
    console.log('Finally 1');
  });
}

teste()
Obs.: A sintaxe "const var = (x) => código" é uma forma de declarar uma função em formato "lambda".

Para resolver o problema, a variável "aguarde" precisa retornar a false no finally() da segunda chamada e no catch da primeira:

Nenhum comentário: