I'd like to know from the html below, if link[rel=import]
, link[rel=stylesheet]
, img
and script
are pending/loaded/failed/aborted without the need to add listeners beforehand and at any point after the event has happened
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<meta charset="utf-8">
<link rel="import" href="template-bundle.html">
<link rel="stylesheet" href="bundle.css">
</head>
<body>
<header><img src="logo.png" alt="App logo"></header>
<!-- Boilerplate... -->
<script src="./app-bundle.js"></script>
</body>
</html>
In other words: Is there an interface which provides something similar to a Bluebird's isPending()
, isResolved()
, isRejected()
methods or a regular ES6 Promise?
Bonus question: Is this something can be achieved using a Service Worker?
Since SW can intercept requests and know their status, I was wondering if I can implement an API which returns a Promise that
- is pending if request is still pending
- is resolved if
load
event fired - is rejected if
error
oraborted
was fired.
Thanks for the help
Update & Solution:
Thanks to the answers of @pritishvaidya and @guest271314, I was able to come up with a viable solution using MutationObserver
that involves watching DOM for additions of resource nodes (link,img,script) and adding a promise to them that will resolve as described above
This works great, with the only caviat that the script tag needs to be inlined in <head>
before any other resource. Here's an example
var resourceNodeSelector = 'link[href],script[src],img[src]';
function watchResource (n) {
var url = n.href || n.src;
if (!n.matches || !n.matches(resourceNodeSelector)) {
return;
}
if (n.status) {
return;
}
n.status = resourceObserver.promises[url] = new Promise(function (resolve, reject) {
n.addEventListener('load', resolve);
n.addEventListener('error', reject);
n.addEventListener('abort', reject);
n.addEventListener('unload', function (l) { delete resourceObserver.promises[url]} );
});
n.status.catch(function noop () {}); //catch reject so that it doesn't cause an exception
}
var resourceObserver = new MutationObserver(function (mutations) {
document.querySelectorAll(resourceNodeSelector).forEach(watchResource);
});
resourceObserver.promises = {};
resourceObserver.observe(window.document, {childList: true, subtree: true});
Once the observer is in place, any valid resource element, should have a status
promise property that you can check at any point in time
document.querySelector('link').status.then(linkLoaded).catch(linkFailed)
A more elegant solution, that does not involve using the expensive querySelectorAll
, should be possible with ServiceWorker, since it can be programmed to intercept and keep track of all resource requests and their status