我正在尝试像这样在<head>
中加载外部脚本:
<script async type='text/javascript' src='//externalprovider.net/our_script.js'></script>
此脚本声明了一个函数window.manager.loadFunction(sid, mid);
,然后将其用于某些组件,如下所示:
componentDidMount() {
window.manager.loadFunction(this.props.ids[0], this.props.ids[1]);
}
我的问题是,从外部提供程序获取脚本的速度很慢,因此该组件有时间在脚本准备好之前挂载。这给出了错误Uncaught TypeError: Cannot read property 'loadFunction' of undefined
。
仅需检查,我复制了完整内容并将其粘贴到<head>
中,该脚本可以按预期工作。所以我的结论是,脚本从外部提供程序加载的速度太慢。不幸的是,这对我们不起作用,因为外部提供程序需要能够动态更改脚本,所以我无法在我们的<head>
中对其进行硬编码。
所以我认为我应该提供一个使用axios加载脚本然后对其进行评估的服务,如下所示:
async getAdsScript() {
try {
const url = '//externalprovider.net/our_script.js';
const src = (await axios.get(url)).data;
const head = document.getElementsByTagName('head')[0];
const newScriptTag = document.createElement('script');
newScriptTag.type = 'text/javascript';
newScriptTag.async = true;
newScriptTag.text = src;
head.appendChild(newScriptTag);
PubSub.publish('AdsScript.loaded', true);
} catch (error) {
console.warn(error);
}
}
然后我要像这样使用它:
loadFunction() {
window.manager.loadFunction(this.props.ids[0], this.props.ids[1]);
}
componentDidMount() {
PubSub.subscribe('AdsScript.loaded', (msg, showing) =>
this.loadFunction());
}
但是这也不起作用,因为我收到了CORS错误Access to XMLHttpRequest at 'https://externalprovider.net/our_script.js' from origin 'https://dev.testserver.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
,我们很遗憾不能要求他们将CORS策略添加到他们的服务器中。
有人知道我该如何解决吗?
答案 0 :(得分:1)
是的,正如您已经回答的那样,您只需从脚本标记中删除async属性即可。但是,在加载外部脚本之前,您的页面将被阻止。如果您与外部服务器的连接速度较慢,则可能会导致应用程序的初始化速度变慢。
如果要执行JS代码并渲染应用程序直到加载外部脚本,则可以执行以下两项操作之一:
OR
Deferred
等待外部脚本加载。您可以在npm的某个lib中找到Deferred或自己编写。这就是它的样子:<script>
function Deferred() {
let resolve = null;
let reject = null;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return {
promise,
resolve,
reject
}
}
window.waitForExternalScript = Deferred();
function onExternalScriptLoad() {
window.waitForExternalScript.resolve();
}
</script>
<script type="text/javascript" src="./your_main_script_here.js"></script>
<script async type="text/javascript" src="//externalprovider.net/our_script.js" onload="onExternalScriptLoad()"></script>
然后在您的应用中:
componentDidMount() {
window.waitForExternalScript.promise.then(() => {
window.manager.loadFunction(this.props.ids[0], this.props.ids[1])
})
}
答案 1 :(得分:0)
显而易见的答案是从async
的脚本标签中删除<head>
:
<script type='text/javascript' src='//externalprovider.net/our_script.js'></script>
我没看到那是因为我对代码的其他部分视而不见。