symfony / ux

Symfony UX initiative: a JavaScript ecosystem for Symfony
https://ux.symfony.com/
MIT License
806 stars 292 forks source link

[LiveComponent] Error handling on Networking Errors #1986

Open FabianKoehnen opened 1 month ago

FabianKoehnen commented 1 month ago

I recently had an failure where in a Live Component Form on a Field validation sometimes there was a net::ERR_HTTP2_PROTOCOL_ERROR which caused the Js to crash (No more field validation or button interaction until reload).

I later also tried how a net::ERR_NETWORK_CHANGED gets handled, which caused the same crash.

grafik

Maybe it might be useful if there would be some recovery or retry method for Faulty Responses so no reload is necessary to be able to interact with the page again

smnandre commented 1 month ago

You can listen to several events to catch/handle errors, in Symfony UX LiveComponent or directly in stimulus... ... but there is clearly something to improve here in term of DX

Maybe can you see with @YummYume who started some work about this (https://github.com/symfony/ux/issues/1891 and following) ?

FabianKoehnen commented 1 month ago

Thanks for the hints i will look into it

Jonhvmp commented 1 month ago

Recentemente, tive uma falha em um formulário de componente ativo em uma validação de campo, onde às vezes havia um net::ERR_HTTP2_PROTOCOL_ERROR que fazia o JS travar (não há mais validação de campo ou interação de botão até a recarga).

Mais tarde, também tentei como um net::ERR_NETWORK_CHANGED é tratado, o que causou a mesma falha.

gráfico

Talvez seja útil se houver algum método de recuperação ou nova tentativa para Respostas com defeito, para que não seja necessário recarregar para poder interagir com a página novamente.

=======================

  1. Implement Automatic Retries Using a library like axios can simplify the implementation of automatic retries in case of errors. Here's an example using axios with automatic retries:
import axiosRetry from 'axios-retry';

// Configure axios to use automatic retries
axiosRetry(axios, { retries: 3 });

function submitForm(data) {
  axios.post('https://www.servo74.de/de/_components/PilotRegisterForm', data)
    .then(response => {
      console.log('Form submitted successfully', response);
      // Process the response here
    })
    .catch(error => {
      console.error('Error submitting the form', error);
      // Handle the error here, show a message to the user, etc.
    });
}
  1. Use Fetch with Retries If you're using fetch, you can manually implement the retry logic:
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (!response.ok) throw new Error('Network response error');
      return response;
    } catch (error) {
      if (i === retries - 1) throw error;
    }
  }
}

function submitForm(data) {
  const options = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  };

  fetchWithRetry('https://www.servo74.de/de/_components/PilotRegisterForm', options)
    .then(response => response.json())
    .then(data => {
      console.log('Form submitted successfully', data);
      // Process the response here
    })
    .catch(error => {
      console.error('Error submitting the form', error);
      // Handle the error here, show a message to the user, etc.
    });
}
  1. Handle Specific Errors You can add logic to handle specific errors, such as ERR_HTTP2_PROTOCOL_ERROR and ERR_NETWORK_CHANGED, and try a recovery or inform the user accordingly:
  if (error.message.includes('ERR_HTTP2_PROTOCOL_ERROR') || error.message.includes('ERR_NETWORK_CHANGED')) {
    // Recovery logic or retry
    alert('Network error. Retrying...');
    return true; // Return true to indicate the retry should continue
  }
  return false; // Return false to indicate the retry should stop
}

async function fetchWithRetry(url, options, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (!response.ok) throw new Error('Network response error');
      return response;
    } catch (error) {
      if (!handleErrors(error) || i === retries - 1) throw error;
    }
  }
}

function submitForm(data) {
  const options = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  };

  fetchWithRetry('https://www.servo74.de/de/_components/PilotRegisterForm', options)
    .then(response => response.json())
    .then(data => {
      console.log('Form submitted successfully', data);
      // Process the response here
    })
    .catch(error => {
      console.error('Error submitting the form', error);
      // Handle the error here, show a message to the user, etc.
    });
}

Conclusion Implementing automatic retries and specific error handling can help ensure that the user does not need to reload the page to interact with the form again. Make sure to inform the user about what's happening and provide appropriate feedback if all retry attempts fail.

I hope I helped you with these examples, my name is Jonh Alex, it's a pleasure. :)