gpt4 book ai didi

javascript - 如何动态加载JS脚本,并发安全?

转载 作者:行者123 更新时间:2023-12-03 04:58:54 25 4
gpt4 key购买 nike

在我的项目中,我有非常标准的 loadScript 方法来动态加载 JS 脚本,完成后会触发回调:

app.utilities.loadScript = function loadScript(url, callback)
{

if (app.scripts[url]===true) {
callback();
} else {

var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;

script.onload = function() {
app.scripts[url] = true;
callback();
}
// Fire the loading
head.appendChild(script);
}
};

在我的项目情况中,我正在使用基于组件的系统。为了说明这个问题,想象一下同一页面上有两个 Google map 组件。两者都是组件的实例。在他们的构造函数中,我调用该方法,就像这样......

  constructor(selector) {

super(selector);

// API load status
this._api = false;
// load the maps API
app.utilities.loadScript('https://maps.googleapis.com/maps/api/js?v=3.exp&key=' + app.config.mapsKey, this.initMap.bind(this));

}

我预计到这样的情况:如果一个组件的两个实例加载相同的脚本,则它不应该被加载两次。因此,您可以看到我如何在 loadScript 帮助程序内部维护已加载脚本的全局数组:app.scripts[url] = true;

但是,此策略不起作用,因为多个 loadScript 调用的启动时间非常接近。由于第一个调用尚未完成(正在进行中),因此第二个调用将启动另一个调用。

我正在考虑立即在全局数组中的脚本上设置“正在加载”状态,但这仍然让我想知道第二个调用如何监听第一个调用准备就绪,因为否则它确实需要这样的触发器回调触发得太快。

我有一种感觉,我可能想得太多了?

编辑:包括解决此问题的代码,基于 @siam 的答案,并添加了一些调整:

app.utilities.loadScriptEvent = function loadScript(url, eventName)
{

if (app.scripts[url] == 'loading') {
return true;
}

else {
app.scripts[url] = 'loading';

var event = new CustomEvent(eventName);

// Adding the script tag to the head as suggested before
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;

// Then bind the event to the callback function.
// There are several events for cross browser compatibility.
//script.onreadystatechange = callback;

script.onload = function() {
app.scripts[url] = true;
app.window.dispatchEvent(event);
}
// Fire the loading
head.appendChild(script);
}
};

请注意,该方法现在名为 loadScriptEvent,并且第二个参数是事件名称,而不是回调。这个想法是,尽管两个组件几乎可以同时调用此函数,但它们都监听相同的单个事件。但这还不够,如果第一个请求已经忙于加载脚本,则仍然必须停止第二个请求。我在加载状态下意识到了这一点。您可以这样调用此方法:

app.utilities.loadScriptEvent('https://maps.googleapis.com/maps/api/js?v=3.exp&key=' + app.config.mapsKey, "gmloaded");
app.window.addEventListener('gmloaded',this.initMap.bind(this));

这个效果很好。组件实例彼此不了解,但脚本仍然只异步加载一次,一旦加载完成,我们就可以立即运行代码。

最佳答案

以下代码可能会让您大致了解如何完成此操作:

// using jQuery

app.utilities.loadScript = function loadScript(url, callback) {
...
script.onload = function(data) {
app.scripts[url] = true;
callback();
...
$(document).trigger('firstRqstCompleted', data);
}
...
}

$(document).on('firstRqstCompleted', function(e, data) {
// do stuff with first request's data
// initiate second request
});

关于javascript - 如何动态加载JS脚本,并发安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42314372/

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