0

I would like to seek your help about xmlhttprequest. I would like to perform xmlhttp request sending out to get pictures repeatly from server only when the previous http response is received.

In server side, I have created http responses which tagged with xmlhttp status =900.So I want to send out the request once the response due to previous request is received, otherwise, the program should wait until its arrival.

For example:

When I press the button somewhere in the browser, it triggers first picture (jpeg) request to server, then waiting the server's response. After getting the Http response with status marked as 900, xmlhttp will decode the response and display the picture on (image).

In the following code, by capturing the packet with wireshark, I think I success to get the right packet flow. However, the picture can not be shown in the DIV.

Can anyone help me ? Thanks a lot and a lot!

    enter code here
      function init(url)
      {
      var xmlHTTP = new XMLHttpRequest();    
      xmlHTTP.open('GET',url,true);
      xmlHTTP.send();
      xmlHTTP.responseType = 'arraybuffer';
       xmlHTTP.onload = function(e)
      {
        var arr = new Uint8Array(this.response);
       var raw = String.fromCharCode.apply(null,arr);
       var b64=btoa(raw);
       var dataURL="data:image/jpeg;base64,"+b64;
       document.getElementById("image").src = dataURL;
       };
      xmlHTTP.onreadystatechange=function(){
      buff(xmlHTTP.status);

       }
       }
      buff(status){
      if (status=900){
        sleep(1000);
      init('/images/photos/badger.jpg');
       }
         }
        function sleep(milliseconds) {
              var start = new Date().getTime();
              for (var i = 0; i < 1e7; i++) {
                if ((new Date().getTime() - start) > milliseconds){
                    break;
                }
              }
          }            
        </script>
         </head>
         <body>
         <div id="image"><h2>picture display here</h2></div>
          <button type="button" onclick=buff(900)>Get Picture</button>

enter code here

allhksar
  • 3
  • 6
  • 900? Are you serious? – Bergi Jun 21 '15 at 17:18
  • `sleep` is a very bad idea. And probably wrong. – Bergi Jun 21 '15 at 17:19
  • i generated status code 900 for unusal usage. it do return 900 and xmlhttprequest can obtain it. Yeah. sleep is quite strange. i get the packets right when i observe from wireshark. but can not display any picture. Thanks for your response. Dude. – allhksar Jun 22 '15 at 14:27

1 Answers1

0

There are several problems with your code.

Markup

The problem with your markup is, that you are using a div tag to display an image. The src attribute is not supported on div tags. You should use an img tag instead like this:

....
<img id="image" />
<button type="button" onclick="buff(900)">Get Picture</button>

Statuscode

Why are you using a status of 900? If the request was correct and the image was loaded, please use a status of 200.

Image loading

Why are you even using an XMLHttpRequest for loading images? You could simply change the src attribute on the img tag and the browser will request the image.

If you want to reload the image you could just refresh the src attribute. If all images a served under the same URL, you can add a request param like the current time:

document.getElementById("image").src = "/images/photos/badger.jpg#" + new Date().getTime();

This way the browser will request the image again and won't use the one allready loaded and cached. See this answer for further info. (Actually the question is nearly the same as yours...)

Sleep function

Your sleep function will use resources because it's a loop that will constantly run for the specified time. While it runs, it will add numbers and do comparisons that are completly unnecessary. please use something like the javascript build in setTimeout():

buff(status) {
  if(status === 900) {
    setTimeout(funciton(){
      init('/images/photos/badger.jpg');
    }, 1000);
  }
}

Update: working example

I set up a working example in the code snippet. It loads images from the same url, but they are served randomly on each request by lorempixel.

I reorganized the image loading. Actually there was another problem. You startet the next image loading with onreadystatechange. This will fire for each change of the readystate and not only when the image is loaded. Therefore I start the next buff() from the onload() like so:

var xmlHTTP = new XMLHttpRequest();    
xmlHTTP.open('GET',url,true);

xmlHTTP.responseType = 'arraybuffer';
xmlHTTP.onload = function(e) {
    var arr = new Uint8Array(this.response);
    var raw = String.fromCharCode.apply(null,arr);
    var b64 = btoa(raw);
    var dataURL = "data:image/jpeg;base64," + b64;
    document.getElementById("image").src = dataURL;
    buff(this.status);
};
xmlHTTP.send();

For convenience I added a button for stopping the loading of new images. For your example you just have to change the imageUrl and imageStatus variables.

var imageUrl = "http://lorempixel.com/400/200/", // set to "/images/photos/badger.jpg" for your example
    imageStatus = 200, // set to 900 for your example
    stopped = true;

function stopLoading() {
    stopped = true;
}

function loadNextImage(url) {
    if(!stopped) { // only load images if loading was not stopped
        var xmlHTTP = new XMLHttpRequest();    
        xmlHTTP.open('GET',url,true);
        
        xmlHTTP.responseType = 'arraybuffer';
        xmlHTTP.onload = function(e) {
            var arr = new Uint8Array(this.response);
            var raw = String.fromCharCode.apply(null,arr);
            var b64 = btoa(raw);
            var dataURL = "data:image/jpeg;base64," + b64;
            document.getElementById("image").src = dataURL;
            buff(this.status); // set the next timer when the current image was loaded.
        };
        xmlHTTP.send();
    }
}

function buff(status) {
    if (status === imageStatus) {
        setTimeout(function() {
            loadNextImage(imageUrl + "?" + new Date().getTime());
        }, 1000);
    } else { 
        // Status does not match with expected status. 
        // Therefore stop loading of further images
        stopLoading();
    }
}

function init() {
    stopped = false;
    loadNextImage(imageUrl);
}


document.getElementById("start").onclick = function(){
    init(imageUrl);
};
document.getElementById("stop").onclick = stopLoading;
<img id="image" />
<button type="button" id="start">Get pictures</button>
<button type="button" id="stop">No more pictures</button>
Community
  • 1
  • 1
jhinzmann
  • 968
  • 6
  • 15
  • Firstly, thanks for your reply. I have a special need to have status 900. I have try the settimeout function, but I find this go wrong. At the beginning , I get the exactly 1 sec time delay , when it sends 2nd request and so on, the delay is not working. It keeps sending request within around 0.1sec.. – allhksar Jun 22 '15 at 00:35
  • Could you post the code where you tried to use `setTimeout`? – jhinzmann Jun 22 '15 at 08:36
  • i just follow yours buff(status) { if(status === 900) { setTimeout(funciton(){ init('/images/photos/badger.jpg'); }, 1000); } } – allhksar Jun 22 '15 at 14:21
  • just updated my answer with an working example. I hope this helps solving your problem – jhinzmann Jun 22 '15 at 22:12
  • @allhksar Please let me know if there are still any problems. If my answer solved your problem, please [accept it](http://stackoverflow.com/help/someone-answers). – jhinzmann Jun 26 '15 at 19:10