0

I need to make the foreach loop on the result return by the ajax. While doing foreach I am checking against each record that image exist or not.

Image Existence Code

function imageExists(url, callback) {
    var img = new Image();
    img.onload = function() { callback(true); };
    img.onerror = function() { callback(false); };
    img.src = url;
}

For each loop

 hotelImagesText = '<ul class="gallery list-unstyled cS-hidden" id="image-gallery">';
    $.each(hotelImagesArr, (index, item) => {
        imageExists(item, function(exists) {
            if (exists) {
                hotelImagesText += '<li data-thumb="'+hotelImagesArr[index]+'"> 
               <img src="'+hotelImagesArr[index]+'"></li>';
             }
    });
});
    hotelImagesText += '</ul>';

When I console it only gives me the above string that has ul. The string inside the imageExists does not concat.

Umair Khan
  • 283
  • 3
  • 13

1 Answers1

1

That's because, even though $.each is synchronous, imageExists is not and therefore the concatenations happen too late.

What you can do is return Promise instances from the latter, and make use of Promise.all.

Demo:

function imageExists(url) {
  return new Promise(resolve => {
    const img = new Image();
    img.onload = () => resolve(true);
    img.onerror = () => resolve(false);
    img.src = url;
  });
}

const hotelImagesArr = [
  'https://www.sample-videos.com/img/Sample-jpg-image-50kb.jpg',
  'https://www.sample-videos.com/img/Sample-jpg-image-100kb.jpg',
  'https://stackoverflow.com/idonotexist.jpg'
];

let hotelImagesText = '<ul class="gallery list-unstyled cS-hidden" id="image-gallery">';

const checks = hotelImagesArr.map(url => imageExists(url));

Promise.all(checks).then(checksResults => {
  for (let i in checksResults) {
    if (checksResults[i]) {
      hotelImagesText += `<li data-thumb="${hotelImagesArr[i]}"><img src="${hotelImagesArr[i]}"></li>`;
    }
  }

  hotelImagesText += '</ul>';

  console.log(hotelImagesText);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Jeto
  • 14,596
  • 2
  • 32
  • 46
  • Thanks for the answer but this is shoowing empty result to me. – Umair Khan Oct 14 '18 at 16:14
  • only – Umair Khan Oct 14 '18 at 16:14
  • @UmairKhan As you can see the sample works. Can you post your updated code (maybe edit the question)? – Jeto Oct 14 '18 at 16:15
  • should i post in comment ? – Umair Khan Oct 14 '18 at 16:18
  • let hotelImagesText = ''; }); } – Umair Khan Oct 14 '18 at 16:19
  • @UmairKhan Did you also change `imageExists` to return a Promise? Maybe you can post your whole code to https://pastebin.com/ – Jeto Oct 14 '18 at 16:21
  • @UmairKhan Your `console.log` needs to be within `Promise.all`'s callback (above where you put it), along with any code that needs to be executed after all checks have been computed. – Jeto Oct 14 '18 at 16:27
  • @UmairKhan You're welcome (you can also mark the answer as accepted if you'd like). Good day – Jeto Oct 14 '18 at 16:31