0

I have a working ajax function

but when I use onprogress I sometimes get half returned html and the console says Uncaught SyntaxError: Invalid or unexpected token but i continues anyway.

here the function

function xhrAJAX ( divID , param2 ) {

    var pcache = (Math.floor(Math.random() * 100000000) + 1);
    var params = "divID="+encodeURIComponent(divID)+"&param2="+encodeURIComponent(param2);
    var xhr = new XMLHttpRequest(); xhr.open("POST", "/file.php?pcache="+pcache, true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.onprogress = function(e) { $("#"+divID).html(e.currentTarget.responseText) ; }
    xhr.send(params);

}

***** I know that If I change the .onprogress with xhr.onreadystatechange = function(e) { if (xhr.readyState == 4) { $("#"+divID).html(e.currentTarget.responseText) ; } } I won't have the console error.... but sometimes, what happens in the php takes long time to execute and want to show the progress.

My PHP8 is configured with NGINX with no output buffer so if I do echo 'stuff'; sleep(3); echo '2'; I see 'stuff' then after 3 seconds see '2' appear.

PLEASE : note that the php portion described here is not the question.

THE QUESTION : is there a way to avoid "half returned html" on the onprogress (in the javascript side) ?

Jintor
  • 607
  • 8
  • 32
  • 1
    No. `responseText` is the raw text buffer. Do not use arbitrary html for streaming. Break it apart into lines where each line is valid html on its own or something like that. – Bergi May 26 '21 at 00:57
  • @Bergi I just saw what you mean, digging further I discovered this "[Violation] Forced reflow while executing JavaScript took 36ms" so it's a millisecond thing – Jintor May 26 '21 at 01:45
  • @Bergi is there a javascript way to "filter" or way to "stack" buffers instead of outputting all received buffers at the same time ? – Jintor May 26 '21 at 01:47
  • As I said, use something like `responseText.split('\n')` and show all lines except the last (incomplete) one. – Bergi May 26 '21 at 01:53
  • @Bergi do you know if there is any way to avoid "reflow while executing" does javascript have some way to detect that ? – Jintor May 26 '21 at 02:52
  • https://stackoverflow.com/questions/41218507/violation-long-running-javascript-task-took-xx-ms – Bergi May 26 '21 at 07:57
  • @Bergi I found and answer to this. XMLHttpRequest is kind of old. fetch is newer and I found a way to stream html (like if I was streaming video, but just plain html with css and executable js....). See my answer below. – Jintor Jun 11 '21 at 04:26

1 Answers1

0

I found the new javascript replacement fetch. with some digging I came up with this streamble html

It also works from within webviews android and IOS ;)

in this scenarion, I have PHP 8 and NGINX with output buffer off, so each echo is pushed while continuing the execution....

function fetchsrteam ( divid , sub , buttonid ) {
    
    var pcache = (Math.floor(Math.random() * 100000000) + 1); 
    var postix = [];
    postix["preventCache"] = pcache;
    postix["divid"] = encodeURIComponent(divid);
    postix["buttonid"] = encodeURIComponent(buttonid);
        
    fetch("/.........php?pcache="+pcache, {
      method: "POST",
      body: JSON.stringify(Object.assign({}, postix)),
      headers: {"Content-type": "application/json; charset=UTF-8"}
    }).then(response => response.body)
      .then(rb => {
        const reader = rb.getReader();
          return new ReadableStream({
            start(controller) {
              function push() {
                reader.read().then( ({done, value}) => {
                  if (done) {
                    console.log('done', done); controller.close(); return;
                  }
                  controller.enqueue(value); $("#"+divid).append(new TextDecoder().decode(value)); push();
                })
              }
            push();
            }
          });
    });

}
Jintor
  • 607
  • 8
  • 32