javascript - 具有外部解析的 Promise.all 永远不会解析
问题描述
我正在开发一个 SPA(单页应用程序)项目,需要以动态和受控的方式(CSS、HTML 和 JS)加载文件
我创建了下面的结构(在此示例中仅用于 CSS),但尽管文件被注入到页面中,但承诺从未得到解决
该结构的一个特点是每个“promise”创建的“resolve”和“reject”都保存在原始“promise”函数之外执行
这是必要的,因为如果“承诺”成功,则必须移除控制事件,如果发生错误,则必须移除元素
'use strict';
const
css=
(
()=>
{
const
load=
url=>
{
return new Promise(
(resolve,reject)=>
{
let
link=document.createElement("link");
link.setAttribute("href",url);
link.setAttribute("rel","stylesheet");
link.addEventListener("load",onSuccess);
link.addEventListener("error",onError);
resolveAhead=resolve;
rejectAhead=reject;
document.head.appendChild(link);
}
);
},
onSuccess=
event=>
{
event.target.removeEventListener("load",onSuccess);
event.target.removeEventListener("error",onError);
resolveAhead(event);
},
onError=
event=>
{
document.head.removeChild(event.target);
rejectAhead(event);
};
let
resolveAhead,
rejectAhead;
return {
load
}
}
)();
Promise.all(
[
css.load("style1.css"),
css.load("style2.css"),
css.load("style3.css"),
css.load("style4.css"),
css.load("style5.css"),
css.load("style6.css")
]
).then(
response=>
{
console.log(response);
alert("Well done");
}
).catch(
response=>
{
console.log(response);
alert("Houston... we've had a problem here");
}
);
解决方案
您的问题是您有两个变量:
let resolveAhead, rejectAhead;
第一次调用.load()
时,将它们设置为正在构建的新 Promise 的 resolve 和 reject 函数。但是,下次调用 时.load()
,您将再次创建一个新的 Promise,并覆盖这些变量以作为新 Promise 的解析/拒绝。然后只能调用最后构造的 Promise 中的 resolve/reject 函数。
您可以在load()
函数内部创建对这些的引用,以便进一步调用load()
不会影响已定义的 resolveAhead 和 rejectAhead 函数:
'use strict';
const css = (() => {
const load = url => {
let resolveAhead, rejectAhead;
const onSuccess = event => {
event.target.removeEventListener("load", onSuccess);
event.target.removeEventListener("error", onError);
resolveAhead(event);
};
const onError = event => {
document.head.removeChild(event.target);
rejectAhead(event);
};
return new Promise(
(resolve, reject) => {
let link = document.createElement("link");
link.setAttribute("href", url);
link.setAttribute("rel", "stylesheet");
link.addEventListener("load", onSuccess);
link.addEventListener("error", onError);
resolveAhead = resolve;
rejectAhead = reject;
document.head.appendChild(link);
}
);
};
return {load};
})();
Promise.all([
css.load("https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"),
css.load("https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"),
]).then(response => {
console.log(response);
alert("Well done");
}).catch(response=> {
console.log(response);
alert("Houston... we've had a problem here");
});
推荐阅读
- python - How do I fix syntax problems in my Python code
- google-maps - 父数据更新时,VueJS子组件GMAP不会重新渲染
- jquery - 在 TypeScript 中导入 jQuery 时,“无法调用类型缺少调用签名的表达式”
- android - 为什么我在 Kotlin 中使用委托时 isBackgroundWindow 返回错误?
- python - Pandas 数据框 - to_json() to_csv() 对于 iso 格式的日期的行为不同
- angular - 在角度元标记中显示特殊字符?
- postman - 邮递员:如何从响应中获取数字字符串值的计数
- python - Python/Stripe 发票创建未添加 line_item
- java - 为什么我不能创建内部类的实例?
- r - 从网络中获取加权矩阵