gpt4 book ai didi

javascript - 有没有办法知道链接/脚本是否仍在挂起或失败

转载 作者:太空狗 更新时间:2023-10-29 14:20:21 24 4
gpt4 key购买 nike

我想从下面的 html 中知道,如果 link[rel=import] , link[rel=stylesheet] , imgscript pending/loaded/failed/aborted 无需事先和事件发生后的任何时间添加监听器

<!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>

换句话说:是否有一个接口(interface)提供类似于 Bluebird 的 isPending() 的接口(interface)? , isResolved() , isRejected()方法还是常规的 ES6 Promise?


附加问题:这是否可以使用 Service Worker 来实现?

由于 SW 可以拦截请求并知道它们的状态,我想知道我是否可以实现一个返回 Promise 的 API

  • 如果请求仍在等待中,则为等待中
  • 如果 load 就解决了事件触发
  • 如果error被拒绝或 aborted被解雇了。

感谢帮助


更新和解决方案:

感谢@pritishvaidya 和@guest271314 的回答,我能够使用 MutationObserver 提出一个可行的解决方案。这涉及监视 DOM 以添加资源节点(链接、img、脚本)并向它们添加将按上述方式解析的 promise

效果很好,唯一需要在 <head> 中内联脚本标签的 caviat在任何其他资源之前。 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});

一旦观察者到位,任何有效的资源元素都应该有一个 status您可以在任何时间点检查的 promise 属性

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

一个更优雅的解决方案,不涉及使用昂贵的 querySelectorAll , ServiceWorker 应该是可能的,因为它可以被编程为拦截和跟踪所有资源请求及其状态

最佳答案

您可以利用 onload , onerror <link>的事件元素;见Browser CSS/JS loading capabilities在右栏。

创建一个对象来存储所有 <link> 的状态请求并解决或拒绝 Promise对应于<link>元素。

拒绝 Promiseonerror事件;使用 .catch()链接到 Promise.reject()处理错误以便 Promise.all()不会停止处理作为参数传递的数组中已解决的 promise 。您也可以throw来自 .catch() 的错误在onerror处理程序到 Promise.all()如果有拒绝Promise应该停止处理 promise 数组中已解决的 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>

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

关于javascript - 有没有办法知道链接/脚本是否仍在挂起或失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39824927/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com