• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Logowanie i obliczanie progresji wykonania skryptu PHP wywołanego przez AJAX

+1 głos
86 wizyt
pytanie zadane 2 czerwca 2021 w JavaScript przez sc4rface Dyskutant (7,710 p.)

Cześć wam, próbuję napisać rozwiązanie, które wyśle żądanie AJAX do pliku PHP, na bieżąco pobierze postęp jego wykonywania (dla wyświetlenia paska postępu) oraz wyświetli we front-endzie wszystkie wiadomości zwrotne przez ten skrypt dostarczane (czyli wszystko co echowane).

Moje rozwiązanie działa połowicznie z dwóch względów, mianowicie:

1. Wiadomości duplikują, a dokładniej "stackują" się, zamiast wyświetlać każdą po kolei. Nadmienię, że zamiast filtracji po stronie klienta chciałbym wyeliminować błąd już na etapie backendu. Wygląda to w ten sposób:

Set up...

Set up... Analyzing...

Set up... Analyzing... Exit

A powinno tak:

Set up...

Analyzing,..

Exit

Nadmienię, że każdy kolejny string jest dopisywany do poprzedniego, nie są to osobne ciągi, stąd porównywanie poprzedniego z aktualnym nie zadziała.

2. Nie mogę obliczyć dokładnego progresu dla paska ze względu na brak parametru e.total z racji używania flush() i ob_flush(), ponieważ bufor jest czyszczony i ta wartość zawsze wynosi 0

$('#import').on('submit', function(e) {

  e.preventDefault();

  $.ajax({
    url: $(this).prop('action'),
    method: $(this).prop('method'),
    xhrFields: {
      onprogress: function(e) {
        $('#logs').append('<p>' + e.target.responseText + '</p>');
        $('progress').val((e.loaded / e.total) * 100);
      }
    },
    success: function(response) {
      console.log(response);
    }
  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="import" method="POST" action="import.php">
  <div id="logs"></div>
  <progress max="100" value="0"></progress>
  <button type="submit">Run</button>
</form>

Plik import.php dla celów testowych do którego odwołuje się formularz.

echo 'Set up...';
ob_flush();
flush();
sleep(1);
    
echo 'Analyzing...';
ob_flush();
flush();
sleep(1);
    
echo 'Exit';
ob_flush();
flush();
sleep(1);

1 odpowiedź

0 głosów
odpowiedź 3 czerwca 2021 przez VBService Mędrzec (162,950 p.)
wybrane 4 czerwca 2021 przez sc4rface
 
Najlepsza

Propozycja do punktu 1-go

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="import" method="POST" action="import.php">
  <div id="logs" data-last-text-ajax=""></div>
  <progress max="100" value="0"></progress>
  <button type="submit">Run</button>
</form>

<script>
$('#import').on('submit', function(e) {
 
  e.preventDefault();
 
  $.ajax({
    url: $(this).prop('action'),
    method: $(this).prop('method'),
    xhrFields: {
      onprogress: function(e) {
        const text = e.target.responseText.replace($('#logs').attr('data-last-text-ajax'), '');
        $('#logs').attr('data-last-text-ajax', e.target.responseText);

        $('#logs').append('<p>' + text + '</p>');
        $('progress').val((e.loaded / e.total) * 100);
      }
    },
    success: function(response) {
      console.log(response);
    }
  });
 
});

</script>

 

Poniżej na obrazku, kod ajax-a uruchomiony przez 3 krotne kliknięcie przycisku Run  wink

 

Propozycja dla 2-go punktu (przy założeniu, że wszystkich znaków wysłanych ze skryptu php nie będzie więcej niż 100)

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form id="import" method="POST" action="import.php">
  <div id="logs" data-last-text-ajax=""></div>
  <progress max="100" value="0"></progress>
  <button type="submit">Run</button>
</form>

<script>
$('#import').on('submit', function(e) {
 
  e.preventDefault();

  if ($('progress').val() > 99) {
    $('#logs').html('');
  }
 
  $('button[type="submit"]').attr('disabled', true);

  $.ajax({
    url: $(this).prop('action'),
    method: $(this).prop('method'),
    xhrFields: {
      onprogress: function(e) {
        const text = e.target.responseText.replace($('#logs').attr('data-last-text-ajax'), '');
        $('#logs').attr('data-last-text-ajax', e.target.responseText);

        $('#logs').append('<p>' + text + '</p>');
        $('progress').val(e.loaded);
      }
    },
    success: function(response) {
      console.log(response);
      $('button[type="submit"]').attr('disabled', false);
    }
  });
 
});
</script>

import.php

<?php

$status_message = ['Set up...', 'Analyzing...', 'Exit'];
$status_message_progress = 100 / count($status_message);

foreach ($status_message as $index => $message) {
  echo $message;
  echo str_repeat(' ', ($status_message_progress - strlen($message)));

  switch ($index) {
    case 0: // Set up...
      // kod dla set up-a
      break;
    case 1: // Analyzing...
      // kod dla analyzing
      break;
    case 2: // Exit
    default:
      // kod dla exit
      echo str_repeat(' ', (100 % count($status_message)));
  }

  ob_flush();
  flush();
  sleep(1);
}

?>

Podobne pytania

0 głosów
1 odpowiedź 177 wizyt
pytanie zadane 10 lutego 2016 w JavaScript przez CzlowiekSkrypt Nałogowiec (26,400 p.)
0 głosów
1 odpowiedź 237 wizyt
+1 głos
0 odpowiedzi 174 wizyt
pytanie zadane 17 marca 2018 w JavaScript przez Honter Użytkownik (720 p.)

87,946 zapytań

136,527 odpowiedzi

304,410 komentarzy

58,313 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...