I am consuming an api in which I want to show the generated data in my HTML. For that I am creating the div elements using JavaScript. When displaying the information it does it without problems, but every time I update the page, the data shows them in a different order. That is, if I have 3 divs, the div that was first will now appear last and thus the order changes each time I update the page.
This is my Javascript code:
const cargar_noticias_recientes = async () => {
const noticias_recientes = document.querySelector('#pnl-body-content-card-reci');
const res = await fetch(`WebService_Default.asmx/cargar_card_noticia_recientes`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: ''
});
const datos = await res.json();
let nuevos = [...datos.d];
nuevos.map(async nuevo => {
const div = document.createElement('div');
const peticion = await fetch(`http://localhost:51482/api/values/${nuevo[3]}`, {
method: 'GET'
});
const imagen = await peticion.blob();
const url = URL.createObjectURL(imagen);
div.innerHTML = `
<div class="body-card body-card-reci ${nuevo[0]}">
<div class="card-title">
<span>Nuevo</span>
</div>
<div class="img-card">
<div class="img" style="background-image: url(${url});"></div>
</div>
<div class="content-card">
<p>
<i class="fas fa-tags"></i> ${nuevo[1]}
</p>
</div>
</div>
`
noticias_recientes.appendChild(div);
});
}
>Solution :
The different order may occur because some of the await-ed promises within the multiple map callbacks may resolve sooner than others, giving a different order of execution.
You can get back the results in their original order by using Promise.all — still allowing the non-JS asynchronous tasks to run independently of each other:
const promises = nuevos.map(async nuevo => {
const div = document.createElement('div');
const peticion = await fetch(`http://localhost:51482/api/values/${nuevo[3]}`, {
method: 'GET'
});
const imagen = await peticion.blob();
const url = URL.createObjectURL(imagen);
div.innerHTML = `
<div class="body-card body-card-reci ${nuevo[0]}">
<div class="card-title">
<span>Nuevo</span>
</div>
<div class="img-card">
<div class="img" style="background-image: url(${url});"></div>
</div>
<div class="content-card">
<p>
<i class="fas fa-tags"></i> ${nuevo[1]}
</p>
</div>
</div>
`;
// Don't append to the DOM yet, but *return*
return div;
});
// Collect the DIVs in the order of the originally fetched data:
const divs = await Promise.all(promises);
// ...And populate the DOM
for (const div of divs) noticias_recientes.appendChild(div);