11

I need to load an image synchronously, that is I need to pause execution of javascript until the image is loaded. Since image.onload is asynchronous, the main function will return before the image is loaded.

I am using canvas, and if the main function returns before the image is loaded, and therefore drawn, other things in the canvas will be drawn before the image. This does not work because the order of drawing on a canvas is very important!

Here is what I've been doing:

var img = new Image();
img.onload = function() {
    //image drawing code here
}
img.src = "blahblahblah";
//function returns here, and other drawing code happens before image is drawn

Is there a way to do this synchronously, or to wait until the image is fully loaded before returning from the function?

3 Answers 3

2

Is there a way to do this synchronously, or to wait until the image is fully loaded before returning from the function?

No. AFAIK, the only thing that can be done synchronously in Javascript is a synchronous XHR call.

In any case, what you should be really doing is setting up a heirarchy of callbacks which implement your dependencies.

Sign up to request clarification or add additional context in comments.

5 Comments

I have a very large loop doing a lot of drawing on the canvas, and it is hard to make the loop pause while the image is loading, which is what I need. If I used the image.onload callback, the image would be drawn after something else in the loop. This causes the image to appear in front of things it should be behind.
In the function which starts the image loading, as the last thing, use setInterval to start a function going which closes over an object that is also closed over by your image.onload callback. The "interval" function should do nothing until a specific flag has been set. That flag should be set by your image.onload callback. When it finds the flag set, the "interval" function should call the next piece of code; the code which draws on top of the "background" image.
You cannot make it pause, you must rid this idea from your mind.
OK. So how would I <i>call</i> the next piece of code, if it is just the next iteration of a loop?
You cannot keep it as an inline loop. You must convert your code to be asynchronous. One loop-like pattern would be recursion. You can time the calls to the function by calling setTimeout(myself, timeout) as the last thing in the recursive function (also allowing you to side-step stack limits).
2

Can't this be solved by refactoring?

Wrap whatever code you need to execute after the image load into a function invoked by the callback (or make that function the callbak).

I see that you say that if the main function returns, other code will execute. Can you wrap that, too? Can you delay it's execution or make it dependent on this onload event or someother event?

You could even dynamically load the source of the other javascript code in the image onload.

1 Comment

Maybe, in theory. In practice, not really. Drawing on a canvas is, by nature, a sequence of ordered steps that must happen one after the other. You can force this to happen with a descending staircase of callbacks but... really... it's just quite sucky to have asynchronous steps in a highly synchronous process. One stage of the assembly line working out of time with everything else, causing jams...
0

I don't think you can do it asynchronously, and think it would be very risky if the path to the image file is wrong. You must consider that onload is a callback, that will be called when the image is fully loaded.

So you have to execute the all drawing code in the callback function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.