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?

asked Nov 18, 2019 at 20:50
\$\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';
});
answered Nov 18, 2019 at 21:33
\$\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\$ Commented 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\$ Commented 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\$ Commented 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\$ Commented Nov 19, 2019 at 14:38

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.