thinkpixellab / PxLoader

PxLoader is a simple JavasScript library for creating preloaders and resource downloaders for HTML5 apps.
http://thinkpixellab.com/pxloader
1.11k stars 173 forks source link

Strategy to handle concurrent HTTP connection limits when preloading video and audio #53

Closed robinnorth closed 8 years ago

robinnorth commented 8 years ago

An issue that I have run into with my usage of PxLoader in my current project is that of the limit on concurrent/parallel HTTP connections imposed by particular browsers (see http://www.browserscope.org/?category=network for a list of limits per browser) causing preloading to appear to stall when attempting to load a large number of video and audio resources. This is because PxLoader makes use of the canplaythrough event to know when to count a video or audio resource as 'loaded' -- unlike with preloading an image, where the entire file is downloaded, resulting in the HTTP connection to that resource being released and enabling the next resource in the connection queue to be loaded, preloading a video or audio file will result in the browser maintaining an open HTTP connection to the resource so that buffering can continue, blocking preloading of any other resources that are waiting for a connection.

I have tried to devise a workaround for this problem for my current project (where I am attempting to preload a number of videos that will be used later on in a single page app, not necessarily immediately after preloading) and have determined that setting the src attribute of the video or audio element used by PxLoader to an empty string after the canplaythrough event is fired results in the browser releasing the HTTP connection used by the resource. This approach probably needs further testing to determine if it has any unwanted side-effects i.e. the browser discarding the previously buffered data. However, if it appears to work, would this be a welcome addition to PxLoader, @joelfillmore? Can you think of any reasons why it wouldn't be a good idea?

An alternative approach would be to load video or audio resources as Blob data, using XMLHttpRequest and then returning a local object URL (from URL.createObjectURL) that represents the resource (which is how PreloadJS works). PxLoaderData could be co-opted to do this, if we expose a means of setting the responseType of the XHR used internally by the plugin, or a new PxLoaderBlob plugin could be implemented. The downside to this is that this won't work in IE9 (if anyone still cares about that...) and that you have to wait for the entire resource to download (which is 'true' preloading, but could be lengthy if used with a large number of resources).

I'd be pleased to submit a PR in response to this, but think that it would be worth asking for some input from @joelfillmore and any other interested users first so we can decide on the best approach to tackling this issue.

robinnorth commented 8 years ago

Some more thoughts on this after testing with my current project...

Modifying PxLoaderVideo and PxLoaderAudio to release HTTP connections after receiving a canplaythrough event does work in that it allows preloading to continue, but obviously prevents the browser from continuing to download more of the assets in the background, as it did previously.

Modifying PxLoaderData to accept an options object so that the responseType of the XHR used by the plugin is hugely useful -- in my test, I used a progress listener to detect when an XHR request had finished and then used URL.createObjectURL to generate a URL that I could either use immediately or store somewhere (e.g. in window.sessionStorage, keyed by the original asset URL) for later use.

In general I would say that preloading audio and video by XHR would probably be the preferable technique for many users, as it's the only way to guarantee that the entire asset has been loaded ahead of time. I will submit a PR for the PxLoaderData changes for sure, but wonder if it's still worth making my proposed changes to PxLoaderVideo and PxLoaderAudio as well...