Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Images may not be completely loaded when afterLoad is called #222

Open
mgreter opened this issue Dec 18, 2019 · 2 comments
Open

Images may not be completely loaded when afterLoad is called #222

mgreter opened this issue Dec 18, 2019 · 2 comments
Assignees
Labels

Comments

@mgreter
Copy link

mgreter commented Dec 18, 2019

As the title says, on afterLoad the images may not yet be completely loaded.

afterLoad: function(element){
	console.log('afterLoad', element[0].complete);
},

This is probably due to the use of an intermediate image object internally.
Once that image is loaded the src attribute of the original image is set.
But there is no guarantee that this image will be available immediately.
I guess this is mostly due to UAs decoding images in a background thread today.
There might be other circumstances that can trigger this race-condition.

I tested this with Chrome/78.0.3904.108 and http://ocbnet.ch/jqlazy/
To trigger it I only have to scroll from the top of the page.
If the threshold is already met on load it seems to be ok.
To circumvent this I added another check in afterLoad:

function imageLoaded(image) {
	return new Promise(function(resolve, reject) {
		if(image.complete) {
			resolve();
		}
		function unbind() {
			image.removeEventListener('load', loaded);
			image.removeEventListener('error', rejected);
		}
		const loaded = function() { unbind(); resolve(); };
		const rejected = function() { unbind(); reject(); };
		image.addEventListener('load', loaded);
		image.addEventListener('error', rejected);
	});
}

afterLoad: function(element){
	console.log('afterLoad', element[0].complete);
	imageLoaded(element[0]).then(function() {
		console.log('Finally loaded it', element[0].complete);
	});
},

image

IMHO it would be great if this could be integrated into this plugin.
Or at least state this race-condition clearly in the documentation.
AFAICT for background-images this might not be solvable cleanly.

@dkern dkern self-assigned this Dec 18, 2019
@dkern dkern added the question label Dec 18, 2019
@dkern
Copy link
Owner

dkern commented Dec 18, 2019

I think you just confused two things. The after load of the image object and the after load (or maybe after handle) of Lazy. The callback is just executed after Lazy does it's job. But i totally understand that in this case the name "load" is confusing and as you stated not true. When i have time i will think about that behavior, but this could have a bigger impact to the whole handling.

Thanks for your submission!

@mgreter
Copy link
Author

mgreter commented Dec 18, 2019

Thanks for the reply, as I mentioned it would at least be great to document this somehow.
I guess one can easy get the impression that this would be the case as it mostly does,
so it can be hard to debug any regressions that stem from this edge condition.

But it also seems I can only trigger this in chrome when I disable caching (probably also the
case when server doesn't allow caching, the images are also downloaded twice as shown in
the network tab). It looks like .on('load', function() { ... }) also works out of the box.

FWIW this pretty much describes the same issue: nolimits4web/swiper#3017

AFAICT there is also a small documentation error on the main page as seen below:

image

The bug we're currently investigating is on iOS, but I thought this might be the main
reason why it happens. Will probably see tomorrow when we test it on a real device.
So hopefully we just have to use another (already existing) callback.

Anyway, maybe you can come up with some solution like re-using the image object or
adding the intermediate image to the DOM instead of "transferring" the src attribute.
Not sure if HTMLImageElement.decode() could be of any help here and converting
it to a Base64 URL might be to CPU intensive.

Thanks und einen schönen Abend noch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants