I was attempting to do the same thing. I was preloading 12 audio and 12 image files in preparation for interactive activities based on them. I was getting the same problem (requests cancelled).
I put together this routine which works for me (Chrome testing done so far).
cacheLessonFiles: function (lessonWords, cacheImg, cacheAudio) {
var
fileName = '',
img = {},
audio = {},
wordIDs = Object.keys(lessonWords)
;
wordIDs.forEach(function (wordID) {
if (cacheImg) {
fileName = lessonWords[wordID].img || wordID;
img = new Image();
img.onload = function () {
console.log('cache: finished caching ' + this.src);
};
img.src = "/img/" + fileName + imageSuffix;
}
if (cacheAudio) {
fileName = lessonWords[wordID].saySpanish || wordID;
audio = new Audio();
audio.onloadeddata = function () {
console.log('cache: finished caching ' + this.src);
};
audioArray.push({a: audio, f:"/audio/" + fileName + audioSuffix});
}
});
setTimeout(loadAudio, AUDIO_LOAD_WAIT);
},
The routine just loads up image files without special handling. The image files were trickier. Instead of just setting the source for all of the audio files in the loop, I populated an array with the audio element and associated source file name (.mp3). I then launched a self-initiating callback in a timeout to process the array, pausing for 200ms between requests.
function loadAudio () {
var
aud = audioArray.pop()
;
aud.a.src = aud.f;
if (audioArray.length > 0) {
setTimeout(loadAudio, AUDIO_LOAD_WAIT);
}
}
One constant and one variable are within the closure, but outside of the cacheLessonFiles() method.
AUDIO_LOAD_WAIT = 200,
audioArray = []
I tried wait times less than 200ms, but the cancelled requests started to reappear.
I'd imagine that clients on the end of slower connections (I'm on fiber) would likely get failures again, but this working well enough for my purposes.