Reputation: 63
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')
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
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
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
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