Is there a way to find out if the link continues / script or it is not executed

I would like to learn from the html below if link[rel=import] , link[rel=stylesheet] , img and script delayed / loaded / unsuccessful / interrupted without the need to add listeners in advance and at any time after the event

 <!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 that provides something similar to the Bluebird isPending() , isResolved() , isRejected() or regular ES6 promise methods?


Bonus question: can this be done using the Service Worker?

Since SW can intercept requests and know their status, I was wondering if I can implement an API that returns Promise, which

  • waiting for the request to complete yet
  • resolved if a load event is fired
  • rejected if error or aborted fired.

thanks for the help


Update and solution:

Thanks to the answers of @pritishvaidya and @ guest271314, I was able to come up with a viable solution using MutationObserver , which includes looking at the DOM to add resource nodes (link, img, script) and adding a promise for them, which will be resolved as described above

This works great with a single cadium that needs to be attached with a script tag in the <head> before any other resource. Here is 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 must have the status property of the promise, which you can check at any time

 document.querySelector('link').status.then(linkLoaded).catch(linkFailed) 

ServiceWorker should have the most elegant solution possible, which is not associated with the use of the expensive querySelectorAll , since it can be programmed to intercept and track all resource requests and their status

+7
javascript dom promise html5
source share
2 answers

You can use the onload , onerror events of the <link> element; see CSS / JS Browser Download Options in the right column.

Create an object to save the status of all <link> requests and allowed or rejected Promise corresponding to the <link> element.

Reject Promise in onerror event; use .catch() chained to Promise.reject() to handle the error so that Promise.all() does not stop processing allowed promises in the array passed as a parameter. You can also throw error from .catch() in the onerror handler to Promise.all() if the rejected Promise should stop processing the allowed promises in the promises array.

In the window.onload event handler, use Promise.all() to process all permitted links using the same function that was called before the window.onload event. To wait for the results of Promise.all() be available, set the src last <script> element to bundle.js in .then() , bound to Promise.all()

 <!DOCTYPE html> <html> <head> <title>App</title> <meta charset="utf-8"> <script> var handleLinks = { links: [], isPending: true }; function handleBeforeLoad() { if (document.querySelectorAll("link").length === 0) { console.log("links loading state is pending..", handleLinks.isPending); } else { handleLinks.isPending = false; Promise.all(handleLinks.links) .then(function(linksContent) { console.log("links resolved:", linksContent , "links loading state is pending.." , handleLinks.isPending); linksContent.filter(Boolean).forEach(function(link) { // `content` property : html `document`, `CSSStyleSheet` // requested at `<link>` element console.log(link); }); // load `bundle.js` document.getElementById("bundle") .src = "bundle.js" }) .catch(function(err) { console.log("link error:", err.message) }) } } handleBeforeLoad(); window.onload = handleBeforeLoad; function handleLink(el) { handleLinks.links.push(Promise.resolve({ content: el.import || el.sheet, type: el.type, rel: el.rel, href: el.href, integrity: el.integrity, isResolved: true })); } function handleLinkError(el) { handleLinks.links.push(Promise.reject(new Error(JSON.stringify({ error: "error loading link", type: el.type, rel: el.rel, href: el.href, integrity: el.integrity, isRejected: true }))).catch(function(err) { // handle error console.log(err); // this will return a resolved Promise return "error requesting link " + el.href; // `throw err` here if any rejected Promise should // stop `Promise.all()` from handling resolved Promise })); } </script> <link onload="handleLink(this)" onerror="handleLinkError(this)" rel="import" href="template-bundle.html" type="text/html"> <link onload="handleLink(this)" onerror="handleLinkError(this)" rel="stylesheet" href="bundle.css" type="text/css"> <!-- this should throw error, file does not exist --> <link onload="handleLink(this)" onerror="handleLinkError(this)" rel="stylesheet" href="bundles.css" type="text/css"> <body> <header><img src="" alt="App logo"></header> <!-- Boilerplate... --> <script id="bundle"></script> </body> </html> 

plnkr http://plnkr.co/edit/DQj9yTDcoQJj3h7rGp95?p=preview

+2
source share

Yes, you can check it in the developer tool. Return to the web page and select check, then the seleck network window will open and there you can check the status.

0
source share

All Articles