Messiah
Messiah

Reputation: 63

Is it a bug in chrome about images load?

My aim is to load some images using style['background-image'] in html, But when I put my code in Ajax, there are something wrong.
If i use async ajax, the images load order is reverse; while i use sync ajax, the images load order is normal.
Especially,it happened in chrome.It's normal in firefox.

html structure is very simple like this

<div class="container">
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
</div>

When i use sync ajax, the JS code like this

function Ajax(url) {
        let xhr = new XMLHttpRequest()
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4 && xhr.status === 200) {
                let slides = Array.from(document.querySelectorAll('.test'))
                for (let i = 1; i < 20; i++) {
                    slides[i].style['background-image'] = `url(/data/gallery/1125425/content/${i})`
                }
            }
        }
        xhr.open('get', url, false)
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
        xhr.send()
    }
    Ajax('https://api.github.com')

And the result is thisenter image description here

We can find it's normal and just like what we think it should be

Howerver, when change the async from false to true,the result is like this.

To show the url doesn't matter this phenomenon, I use a public API by github. And now we see the result in the network panel enter image description here

We can see the last image is loaded first, just a reverse order compared with our first try.

In fact, this phenomenon won't happen in firefox, so i guess is it a bug in chrome?

I've put my code into Codepen.
UPDATE: i thought lt's caused by Promise, after then i noticed it's not. So i change the title

Upvotes: 3

Views: 114

Answers (2)

Kaiido
Kaiido

Reputation: 137006

No it's not a bug per se, even if still weird.

This happens because the browser won't recalculate the styles of your elements during this for loop, but only after the js execution has ended and all the DOM changes have been made.

What happens in the next steps (style recalc -> loading of new resources) is up to the implementation.

If you want a fixed order (even if I don't see why you would), you can force a reflow at every loop iteration:

(() => {
  let slides = Array.from(document.querySelectorAll('.test'))
  for (let i = 0; i < slides.length; i++) {
   slides[i].style['background-image'] = `url(/${i})`
   document.body.offsetWidth; // force reflow
  }
})();
console.log("check the 'Network Panel' of your dev-tools");
<div class="container">
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
</div>

Upvotes: 0

dhilt
dhilt

Reputation: 20814

Debugging your codepen, I found out that any kind of scope wrapping reverses the order. This one:

  let slides = Array.from(document.querySelectorAll('.test'))
  for (let i = 0; i < slides.length; i++) {
   (() => slides[i].style['background-image'] = `url(/data/gallery/1125425/content/${i})`)();
  }

And this:

(() => {
  let slides = Array.from(document.querySelectorAll('.test'))
  for (let i = 0; i < slides.length; i++) {
   slides[i].style['background-image'] = `url(/data/gallery/1125425/content/${i})`
  }
})();

So the Promise has nothing to do with, I guess.

But also I would say that the forward order (in my case) is not strict forward order, it is buggy: 0, 1, 2, 3, 4, 5, 10, 8, 7, 19, etc and this sequence does not change from time to time during a session.

Upvotes: 2

Related Questions