4
\$\begingroup\$

This is really a simple affair, I just wonder if there is a better way to do it:

let el = document.querySelectorAll('#comic img');
let loadPromise = new Promise(function(resolve, reject) {
    let ticker = setInterval(() => {
        if (el[0].complete) {
            clearInterval(ticker);
            resolve();
        }
    }, 100);
    setTimeout(() => {
        clearInterval(ticker);
        reject('Timeout');
    }, 5000)
});

loadPromise.then(() => {
    console.log(el[0].naturalWidth);
    let container = document.querySelectorAll('.main-wrapper > div > section > section.column.column-1.grid-left-4.grid-width-16');
    container[0].style.width = (el[0].naturalWidth + 420) + 'px';
});

I must wait for the image to load, so I know its size so that I can adjust an element on the page.

But setInterval(aka polling the element) seems so... medieval. Is there a nicer way in modern JS?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

"Must wait for the image to load" ... "Is there a nicer way?"

Yes,
At first, instead of accessing the image by index el[0] - extract the image at once and give the variable meaningful name:

let img = document.querySelectorAll('#comic img')[0];

Next, you need to embed "load" event listener into Promise executor function to ensure the image has loaded:

let loadPromise = new Promise(function(resolve, reject) {
    img.addEventListener('load', function() {
       resolve();
    });
    setTimeout(() => {
        if (!img.complete) reject('Timeout');
    }, 5000)
});
loadPromise.then(() => {
    console.log(img.naturalWidth);
    let container = document.querySelectorAll('.main-wrapper > div > section > section.column.column-1.grid-left-4.grid-width-16');
    container[0].style.width = (img.naturalWidth + 420) + 'px';
});
\$\endgroup\$
4
  • \$\begingroup\$ This answer is very poor -1. Image.complete property indicates the status of the loading process not the whether or not the image has actually loaded. As the image is queried from the page it may have already loaded in which case nether the load or timeouts will resolve the promise. \$\endgroup\$
    – Blindman67
    Nov 19, 2019 at 13:27
  • \$\begingroup\$ @Blindman67, such a comment does not consider situations when img element was added to the document, but its src attribute is set or changed/delayed in another event/function \$\endgroup\$ Nov 19, 2019 at 13:34
  • \$\begingroup\$ Even if you set the src the image can fail to load and the load event will not fire while the timeout will not detect that there was an error as complete will be true \$\endgroup\$
    – Blindman67
    Nov 19, 2019 at 13:39
  • \$\begingroup\$ Ugh. Must have been really tired to not think of looking into events. The .complete attribute criticism is valid, though I'm not certain it is trivial to fix the promise. Arguably however it can be simplified further by not promisifying the callback, which conveniently also avoids the .complete issue. \$\endgroup\$
    – martixy
    Nov 19, 2019 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.