I have an array of URLs that I want to download sequentially, 2 URLs at the time.
var urls = [url1,url2,url3,url4,url5];
The loop should download all the URLs using some async function, 2 urls at the time in the order they appear in the array.
The basic sequential loop is done using .reduce
that works like this:
preloadPromise = urls.reduce(function(p, url) {
return p.then(WinJS.Utilities.Scheduler.schedulePromiseBelowNormal).then(function() {
return preloadOneAsync(url);
}).then(null, function(error) {
if (error.name !== "Canceled") {
logger.error("Could not create preloaded " + url, error);
}
});
}, WinJS.Promise.as());
Now I want to introduce parallel downloads of 2 URLs at the same time.
So it would download: [url1,url2] then [url3,url4] and finally [url5]
Also the result of the function should be the results of every download promise, similar to how WinJS.Promise.join
works.
Let's abstract out the function to break the array into tuples
function chunkBy(array, n) {
var chunks = [];
for (var i=0; i<array.length; i+=n)
chunks.push(array.slice(i, n));
return chunks;
}
and the function that does the work for each item:
function tryToLoad(url) {
return WinJS.Utilities.Scheduler.schedulePromiseBelowNormal() // not sure
.then(function() { return preloadOneAsync(url); })
.then(null, function(error) {
if (error.name !== "Canceled") {
logger.error("Could not create preloaded " + url, error);
}
});
}
A function that does the work for multiple items in parallel would be just
function loadAll(urls) {
return WinJS.Promise.join(urls.map(tryToLoad));
}
so we can now use this in the generation of the sequence:
preloadPromise = chunkBy(urls, 2).reduce(function(p, urls) {
return p.then(function(prevResults) {
return loadAll(urls).then(function(results) {
return prevResults.concat(results);
});
});
}, WinJS.Promise.as([]));
The array of results is passed through the p
chain, always growing after each step.