0

I have an array of picture URLs and I need to show each picture for an exact amount of time (750 ms). I have implemented the page using setTimeout function and it works fine except that the time i want to display each picture grows to 752ms or even more...

According to this post and many others, I have created a new function:

        function getTimestamp() 
        { 
            return window.performance.now(); 
        }

        function waitFor( time, nextFunction )
        {
            var t1 = getTimestamp();
            console.log("Start Time: " + t1);

            var t2 = getTimestamp();

            while ( t2 - t1 <= time)
            {
                t2 = getTimestamp();
            }

            console.log("End Time: " + t2);

            nextFunction();
        }

I know that javascript is excuted in a single thread and that if i run a wait function implemented using a while statement, the main thread of the page will be frozen. In other words, my function is executed synchronous. In my case, that "frosen" time is used to present the pictures, so it's fine by me.

I am changing the image source as following:

            var url = "images/Practice" + imagesArr[randomNum] +".png";
            console.log("image path: " + url);
            imagesArr.splice(randomNum, 1);
            pictureImg.src = url;
            pictureImg.style.display="block"; 

Despite the fact that my code changes the image source perfectly, sometimes the browser won't change the image. It displays only the first picture that was displayed and sometimes it mixes up the order.

My page is here.

Importantly, my website will be running only in Chrome.

I am really puzzled here and i would appreciate any help!!!

Thank you, Max.

Community
  • 1
  • 1
Max Z
  • 87
  • 1
  • 1
  • 10
  • Note that all the javascript will be frozen.. including your event handlers for the UI.. – Sampath Liyanage Nov 09 '14 at 13:26
  • setTimeout(f,t) will be called after a minimum 't' ms. I have had very bad experiences will timers: they work as intended, but not as expected by us. For instance, if you have other events lined up in the event loop, it will finish them all and then do this. That is your event loop would already have many events lined up, all setTimeout does is, after 't' ms, puts this 'f' at the end of the event queue. Hence, in practise it might take a lot longer than the expected time. Just thought I will give you a heads up! – Aravind Nov 09 '14 at 13:28

2 Answers2

3

...except that the time i want to display each picture grows to 752ms or even more...

If being out by 2ms is a problem, you can't use a browser for this.

Basically, when you change the src of the image, the browser isn't required to update its display right away, and frequently won't; instead, it may wait until the current "task" in the JavaScript code completes (e.g., the event handler returns, your timer function returns, etc.). So updating src and locking the browser isn't going to do what you want.

If you change the src, do a setTimeout(..., 750);, and then return, that's basically the best you can do in a browser. It'll update its display and call you back in roughly 750ms to do your next thing. You can't get more precise than that.

But if you want to continue to try your busy-wait approach, one way would be to set src, grab the current time, do a setTimeout(..., 0), and then enter your busy-wait when the timer fires (which will be somewhere between 0 and 10 milliseconds later). Since you know when you changed the src, you know when 750ms later is. But note that you don't know when the human started seeing the image, which could easily be a couple of milliseconds after src was set.


Side note: I assume you're pre-loading these images before starting, and so when you set src, they come from cache. If not, you'll want to do that, as the delay while the image is being fetched is likely to be a couple of dozen milliseconds at best, quite a lot more at worst.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Image loading is async operation.

When you set image object's src property

pictureImg.src = url;

Your browser schedules async request to load that image. But actual request never happens, because you've blocked whole thread.