が、私は動的にJSのスクリプトをロードするには、かなり標準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);
}
};
を、私は、コンポーネントベースのシステムで働いています。この問題を説明するには、同じページに2つのGoogleマップコンポーネントがあるとします。どちらもコンポーネントのインスタンスです。そのような彼らのコンストラクタでは、私は
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));
}
は、私は、コンポーネントの2つのインスタンスが同じスクリプトをロードする場合、それは二回ロードされるべきではないという事態を予想...、メソッドを呼んでいます。そのため、loadScriptヘルパーの内部で、すでにロードされているスクリプトのグローバル配列を保持しています。app.scripts [url] = true;
しかし、複数のloadScript呼び出しが相互に非常に近く開始されるため、この方法は機能しません。最初のものはまだ完了していないので(進行中)、2番目の呼び出しが別の呼び出しを開始します。
私はすぐにグローバル配列内のスクリプトに "ローディング"ステータスを設定することを検討していますが、そのようなトリガーが必要なので、2番目の呼び出しがどのように最初のものを聞くことができるか不思議ですさもなければ、コールバックがあまりにも早く発生します。
私はおそらくこれを思っている気がしますか?編集
:少し微調整して、@siamによって回答に基づいてこれを解決したコードを含むは、追加:メソッドは今loadScriptEventということ
が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);
}
};
注意、および第二パラメータことコールバックではなくイベント名です。 2つのコンポーネントがほぼ同時にこの呼び出しを行うことができたとしても、両方とも同じ単一のイベントを聴いているという考えがあります。これでは十分ではありません。最初のスクリプトが既にスクリプトの読み込みに忙しい場合は、2番目の要求を停止する必要があります。私はロード状態でそれを実現しました。このメソッドを次のように呼び出します。
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));
これはうまく動作します。コンポーネントインスタンスは互いの知識を持っていませんが、スクリプトはまだ非同期に一度だけロードされます。一度コードを実行するとすぐに実行できます。
使用 'setInterval'最初の要求が完了したかどうかをチェックするのと、それは、第2の1を開始している場合と、その区間をクリアする – m87
@サイアム。私はそのような答えを恐れていたが、唯一の方法かもしれない。ただし、2つ目の要求は最初の要求を認識していません(2つのコンポーネントインスタンスが互いを認識しないため)。 – Ferdy
um ...多分別の方法があります。最初の要求が完了したときにトリガーされるカスタムイベントを作成できます。そのイベントで最初のリクエストの 'data'を渡すこともできます。 – m87