有没有办法知道链接/脚本是否仍然挂起或失败
Is there a way to know if a link/script is still pending or has it failed
我想从下面的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>
换句话说:是否有一个接口提供类似于Bluebird的isPending()
、isResolved()
、isRejected()
方法或常规ES6-Promise的东西?
额外的问题:这是使用服务人员可以实现的吗?
由于SW可以拦截请求并知道它们的状态,我想知道我是否可以实现一个API,它返回一个承诺
- 如果请求仍处于挂起状态,则为挂起状态
- 如果触发
load
事件,则解决 - 如果CCD_ 9或CCD_
感谢的帮助
更新&解决方案:
多亏了@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});
一旦观察者就位,任何有效的资源元素都应该有一个status
promise属性,您可以在任何时间点检查
document.querySelector('link').status.then(linkLoaded).catch(linkFailed)
ServiceWorker应该可以提供一个更优雅的解决方案,不需要使用昂贵的querySelectorAll
,因为它可以被编程为拦截和跟踪所有资源请求及其状态
可以使用<link>
元素的onload
、onerror
事件;请参阅右栏的浏览器CSS/JS加载功能。
创建一个对象来存储与<link>
元素对应的所有<link>
请求和已解决或已拒绝的Promise
的状态。
在onerror
事件中拒绝Promise
;使用链接到Promise.reject()
的.catch()
来处理错误,这样Promise.all()
就不会停止处理作为参数传递的数组中已解析的promise。如果任何被拒绝的Promise
应停止处理promise数组中已解决的promise,您也可以从onerror
处理程序的.catch()
到Promise.all()
的throw
错误。
在window.onload
事件处理程序中,使用Promise.all()
处理所有已解析的链接,使用在window.onload
事件之前调用的相同函数。要等待Promise.all()
的结果可用,请在链接到Promise.all()
的.then()
处将最后一个<script>
元素的src
设置为bundle.js
<!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>
plnkrhttp://plnkr.co/edit/DQj9yTDcoQJj3h7rGp95?p=preview
是的,您可以在开发人员工具中进行检查。右键单击网页并选择检查,然后窗口将打开选择网络选项,您可以在那里检查状态。
- JavaScript执行暂时挂起页面
- 是定义的操作系统睡眠/挂起期间setTimeout的行为
- Chrome浏览器“;挂起”;同时在循环中执行AJAX请求
- fullcalendar在删除导致浏览器挂起的多个事件时速度较慢
- 应用将图表转换为图像的jqplot代码时Chrome挂起
- 如何在不使用Internet Explorer的情况下从未挂起的HTML文件执行程序
- MongoDB collection.find()查询挂起
- 使用子字符串方法时应用程序挂起的原因
- 如何在AngularJS中取消挂起的请求
- 从node.js应用程序调用Mongoose Model.save()时挂起
- Chrome,Safari在从本地存储读取时挂起,而Firefox很好
- IE 10 挂起 XMLHttpRequest 6 分钟,然后响应请求(使用 AngularJS 实现 CRSF)
- 挂起 JavaScript 键关闭事件
- 此 JavaScript 对象中定义的值是否实际起作用
- HERE 映射 JS API v3 集群提供程序挂起,添加许多数据点
- 如何查明SignalR客户端上是否有挂起的请求
- JS调试器是否挂起整个JS事件循环
- 如何检查Promise是否处于挂起状态
- 是否有可能在单击复选框时停止更改,挂起某些复选框
- 有没有办法知道链接/脚本是否仍然挂起或失败