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);