Dog*_*oku 7 javascript html5 dom promise
我想从HTML知道以下,如果link[rel=import],link[rel=stylesheet],img和script被挂起的加载/失败/中止/ ,而无需事先并在任何时候添加侦听器的事件发生后,
<!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>
Run Code Online (Sandbox Code Playgroud)
换句话说:是否有提供类似蓝鸟的一些接口isPending(),isResolved(),isRejected()方法或常规ES6承诺?
奖金问题:这可以通过服务工作者实现吗?
由于SW可以拦截请求并知道它们的状态,我想知道我是否可以实现一个返回Promise的API
load事件被触发,则解决error或被aborted解雇,则被拒绝谢谢您的帮助
更新和解决方案:
感谢@pritishvaidya和@ guest271314的答案,我能够提出一个可行的解决方案MutationObserver,包括观察DOM添加资源节点(链接,img,脚本)并向他们添加一个将如上所述解决的承诺
这非常有效,只有<head>在任何其他资源之前脚本标记需要内联的空洞.这是一个例子
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});
Run Code Online (Sandbox Code Playgroud)
一旦观察者到位,任何有效的资源元素都应该具有status可以在任何时间点检查的promise属性
document.querySelector('link').status.then(linkLoaded).catch(linkFailed)
Run Code Online (Sandbox Code Playgroud)
querySelectorAllServiceWorker应该可以实现更优雅的解决方案,不涉及使用昂贵的解决方案,因为它可以编程为拦截并跟踪所有资源请求及其状态
您可以利用onload元素onerror的事件<link>;请参阅右栏的浏览器 CSS/JS 加载功能。
创建一个对象来存储与该元素对应的所有请求的状态<link>以及已解决或拒绝。Promise<link>
Promise在活动中拒绝onerror;使用.catch()链接到来Promise.reject()处理错误,这样Promise.all()就不会停止处理作为参数传递的数组中已解决的承诺。您还可以在处理程序中出错,如果throw有任何被拒绝的内容,则应停止处理承诺数组中已解决的承诺。.catch()onerrorPromise.all()Promise
在window.onload事件处理程序中,使用事件Promise.all()之前调用的相同函数来处理所有已解析的链接window.onload。要等待 的结果Promise.all()可用,请将src最后一个<script>元素设置bundle.js为.then()链接到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>
Run Code Online (Sandbox Code Playgroud)
plnkr http://plnkr.co/edit/DQj9yTDcoQJj3h7rGp95?p=preview