Promise.all 外部解决永远解决不了
Promise.all with external resolve never resolves
我正在做一个 SPA(单页应用程序)项目,需要以动态和受控的方式加载文件(CSS、HTML 和 JS)
我创建了下面的结构(在此示例中仅用于 CSS),但是尽管文件已注入页面,但承诺从未得到解决
该结构的一个特点是每个创建的“promise”的“resolve”和“reject”都被保存在原始“promise”函数之外执行
这是必要的,因为如果“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 的解析和拒绝函数。但是,下次调用 .load()
时,您将再次创建一个新的 Promise,并将这些变量覆盖为新 Promise 的 resolve/reject。然后只能调用最后构造的 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");
});
我正在做一个 SPA(单页应用程序)项目,需要以动态和受控的方式加载文件(CSS、HTML 和 JS)
我创建了下面的结构(在此示例中仅用于 CSS),但是尽管文件已注入页面,但承诺从未得到解决
该结构的一个特点是每个创建的“promise”的“resolve”和“reject”都被保存在原始“promise”函数之外执行
这是必要的,因为如果“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 的解析和拒绝函数。但是,下次调用 .load()
时,您将再次创建一个新的 Promise,并将这些变量覆盖为新 Promise 的 resolve/reject。然后只能调用最后构造的 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");
});