I'm writing a little proof of concept thing, which downloads all my HTML assets via fetch()
. Currently, I query all the tags with a compatible asset and run it through a for loop for each asset type. What I need to do is run a callback function after all the requests in the loops have finished. I tried await but it downloads each asset one by one. How can I do this?
const scripts = document.querySelectorAll("script");
const links = document.querySelectorAll("link");
const images = document.querySelectorAll("img");
for (const script of scripts) {
(async (s) => {
const doIgnore = s.getAttribute("data-ignoreload");
if (doIgnore) return;
const src = s.getAttribute("data-src");
if (!src) {
console.error("Script does not have a data-src prop.");
return;
}
fetch(src)
.then(x => x.text())
.then(r => {
const newScript = document.createElement("script");
newScript.innerHTML = r;
document.body.appendChild(newScript);
})
.catch(err => {
console.error(`Error loading script with src ${src}: ${err}`);
});
})(script);
}
for (const link of links) {
(async (l) => {
const doIgnore = l.getAttribute("data-ignoreload");
if (doIgnore) return;
const rel = l.getAttribute("rel");
if (!(rel == "stylesheet")) {
return;
}
const href = l.getAttribute("data-href");
if (!href) {
console.error("Stylesheet does not have a data-href prop.");
return;
}
fetch(href)
.then(x => x.text())
.then(r => {
const newStyle = document.createElement("style");
newStyle.innerHTML = r;
document.head.append(newStyle);
})
.catch(err => {
console.error(`Error loading stylesheet with href ${href}: ${err}`);
});
})(link);
}
for (const image of images) {
(async (i) => {
const doIgnore = i.getAttribute("data-ignoreload");
if (doIgnore) return;
const src = i.getAttribute("data-src");
if (!src) {
console.error("Image does not have a data-src prop.");
return;
}
fetch(src)
.then(x => x.blob())
.then(r => {
const url = URL.createObjectURL(r);
i.setAttribute("src", url);
})
.catch(err => {
console.error(`Error loading image ${src}: ${err}`);
});
})(image);
}
CodePudding user response:
Push all of your promises into an array, and then use Promise.allSettled(promises).then((results) => {})
Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
Example:
const promises = images.map(async (image) => {
// do some async work
return fetch(whatever); // don't .catch this
})
Promise.allSettled(promises).then((results) => {
// results is a result of errors or successes
})