Question

I need to do something like this:

  • Execute a piece of code
  • Start to load an image and block the script execution
  • When the image is loaded resume the execution
  • Execute the rest of the code

I know that the simplest way is to assign a function on the onload event of the image and then execute the rest of the code in the function, but if it's possible i want to have a "linear" behaviour blocking the script execution and then resume it. So, is there a cross-browser way to do this?

Was it helpful?

Solution

The only way to block script execution is to use a loop, which will also lock up most browsers and prevent any interaction with your web page.

Firefox, Chrome, Safari, Opera and IE all support the complete property, which was finally standardised in HTML5. This means you can use a while loop to halt script execution until the image has finished downloading.

var img = new Image();
img.src = "/myImage.jpg";
document.body.appendChild(img);
while (!img.complete) 
{
    // do nothing...
}

// script continues after image load

That being said, I think you should look at ways of achieving your goal without locking up the browser.

OTHER TIPS

If you don't mind having a preprocessing step, try Narrative Javascript, which you can

image.onload = new EventNotifier();
image.onload.wait->();

This suggestion is not exactly what you asked for, but I offer it as a possible alternative.

Create a CSS class with the background-image you want to use. When your app starts, assign this CSS class to a DIV that is either hidden out of site or sized to zero by zero pixels. This will ensure the image is loaded from the server. When you want to load the image (step two above), use the CSS class you create; this will happen quickly. Maybe quickly enough that you need not block the subsequent code execution?

I wouldn't try to block script execution completely, as that could make the browser slow down, or even alert the user that a script is taking too long to execute.

What you can do is 'linearize' your code by using events to finish work. You will need to add a time out to the function, as the image may never load.

Example:

var _img = null; 
var _imgDelay = 0;
var _finished = false;

function startWork(){
   _img = document.createElement('img');
   _img.onload = onImgLoaded;
   _img.src = 'yourimg.png';

   // append img tag to parent element here

   // this is a time out function in case the img never loads,
   // or the onload event never fires (which can happen in some browsers) 
   imgTimeout();   
}

function imgTimeout(){
   if (_img.complete){
      // img is really done loading
      finishWork();
   }
   else{
      // calls recursively waiting for the img to load
      // increasing the wait time with each call, up to 12s
      _imgDelay += 3000;

      if (_imgDelay <= 12000){ // waits up to 30 seconds
         setTimeout(imgTimeout, _imgDelay);
      }
      else{
         // img never loaded, recover here.
      }
   }
}

function onImgLoaded(){
   finishWork();
}

function finishWork(){
   if (!_finished){
      // continue here
      _finished = true;
   }
}

You can use xmlhttprequest and use synchronous mode.

var url = "image.php?sleep=3";
var img = new Image;
var sjax = new XMLHttpRequest();
img.src = url;
sjax.open("GET", url, false);
sjax.send(null);
alert(img.complete);

The trick here is we load the same image twice, first by using the Image object, and also by using ajax in synchronous mode. The Image object isn't needed, I just assumed that's how you want to load it. The key though is that if ajax completes, then the image will be fully downloaded an in the browser's cache. As such, the image will also be available for use by the Image object.

This does assume that the image is served with cache friendly http headers. Otherwise, it's behavior might vary in different browsers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top