JavaScriptファイルを動的にロードする


168

JavaScriptファイルを確実かつ動的にロードするにはどうすればよいですか?これは、「初期化」されたときにコンポーネントが必要に応じてすべてのJavaScriptライブラリスクリプトを動的にロードするモジュールまたはコンポーネントを実装するために使用できます。

コンポーネントを使用するクライアントは、<script>このコンポーネントを実装するすべてのライブラリスクリプトファイル(および手動でタグをWebページに挿入)をロードする必要はありません。「メイン」コンポーネントスクリプトファイルのみです。

メインストリームのJavaScriptライブラリはどのようにこれを実現しますか(プロトタイプ、jQueryなど)? これらのツールは、複数のJavaScriptファイルを単一の再配布可能な「ビルド」バージョンのスクリプトファイルにマージしますか?または、補助的な「ライブラリ」スクリプトを動的にロードしますか?

この質問への追加:動的に含まれるJavaScriptファイルがロードされた後にイベントを処理する方法はありますか? プロトタイプにはdocument.observe、ドキュメント全体のイベントがあります。例:

document.observe("dom:loaded", function() {
  // initially hide all containers for tab content
  $$('div.tabcontent').invoke('hide');
});

スクリプト要素で使用できるイベントは何ですか?


回答:


84

ダイナミックスクリプトタグを書くことができます(Prototypeを使用):

new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});

ここでの問題は、外部スクリプトファイルが完全に読み込まれるタイミングがわからないことです。

次の行に依存するコードが必要になることがよくあります。

if (iNeedSomeMore) {
    Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
    myFancyMethod(); // cool, no need for callbacks!
}

コールバックを必要とせずにスクリプトの依存関係を注入するスマートな方法があります。同期AJAXリクエストを介してスクリプトをプルし、グローバルレベルでスクリプトを評価するだけです。

プロトタイプを使用する場合、Script.loadメソッドは次のようになります。

var Script = {
    _loadedScripts: [],
    include: function(script) {
        // include script only once
        if (this._loadedScripts.include(script)) {
            return false;
        }
        // request file synchronous
        var code = new Ajax.Request(script, {
            asynchronous: false,
            method: "GET",
            evalJS: false,
            evalJSON: false
        }).transport.responseText;
        // eval code on global level
        if (Prototype.Browser.IE) {
            window.execScript(code);
        } else if (Prototype.Browser.WebKit) {
            $$("head").first().insert(Object.extend(
                new Element("script", {
                    type: "text/javascript"
                }), {
                    text: code
                }
            ));
        } else {
            window.eval(code);
        }
        // remember included script
        this._loadedScripts.push(script);
    }
};

クロスドメインで機能させるにはどうすればよいですか?(からスクリプトを読み込んでいますhttp://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js
user2284570


@Ciastopiekarz:私は制御できませんweb.archive.org
user2284570 2017年

次に、他のプログラムを使用してアクセスしたいデータをこすり取り、自分で提供する必要があります
David Schumann

Ajax.Requestとは何ですか?
bluejayke

72

JavaScriptにはインポート/インクルード/要求はありませんが、目的を達成するには主に2つの方法があります。

1-AJAX呼び出しでロードしてからevalを使用できます。

これは最も簡単な方法ですが、Javascriptの安全設定のため、ドメインに限定されます。evalを使用すると、バグやハッキングの可能性が広がります。

2-HTMLのスクリプトURLを含むスクリプトタグを追加します。

間違いなく最善の方法です。外部サーバーからでもスクリプトを読み込むことができ、ブラウザーのパーサーを使用してコードを評価するので問題ありません。タグは、Webページの先頭または本文の下部に配置できます。

ここでは、これらのソリューションの両方について説明し、説明します。

今、あなたが知っておくべき大きな問題があります。これは、リモートでコードをロードすることを意味します。最新のWebブラウザーは、パフォーマンスを向上させるためにすべてを非同期でロードするため、ファイルをロードして現在のスクリプトを実行し続けます。

つまり、これらのトリックを直接使用すると、ロードを要求した後、次の行で新しくロードされたコードを使用できなくなります。

EG:my_lovely_script.jsにはMySuperObjectが含まれています

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

次に、F5を押してページをリロードします。そしてそれはうまくいきます!混乱しています...

それで、それについて何をすべきか?

まあ、あなたが私があなたに与えたリンクで著者が提案するハックを使うことができます。要約すると、急いでいる人のために、スクリプトが読み込まれたときに彼はイベントを使用してコールバック関数を実行します。したがって、リモートライブラリを使用するすべてのコードをコールバック関数に配置できます。EG:

function loadScript(url, callback)
{
    // 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 = callback;

   // fire the loading
   head.appendChild(script);
}

次に、スクリプトがラムダ関数に読み込まれた後で、使用するコードを記述します。

var myPrettyCode = function() {
    // here, do what ever you want
};

次に、すべてを実行します。

loadScript("my_lovely_script.js", myPrettyCode);

はい、分かりました。しかし、これをすべて書くのは面倒です。

まあ、その場合は、いつものように素晴らしいjQueryフレームワークを使用して、同じことを1行で行うことができます。

$.getScript("my_lovely_script.js", function() {
    alert("Script loaded and executed.");
    // here you can use anything you defined in the loaded script
});

11
この答えがどれほど過小評価されているか信じられません。ありがとうございました。
naftalimich

2
「成功するための3つの秘密の手順に従うだけで」金持ちになることを約束しない限り、人々は最初の行を超えて読むのが好きではないためだと思います。
コスタ

これは機能します。ここで私の経験を共有することで、時間を節約できれば幸いです。Angular 6と適用されたテンプレート(html、css、jquery)を使用しています問題は、テンプレートに、html要素が読み込まれてリスナーイベントをアタッチした後に読み込まれるjsファイルがあることです。Angularアプリが読み込まれた後、そのjsファイルを実行するのは困難でした。angular app(angular.json)スクリプトタグに追加すると、それらがバンドルされますが、ロード後にそのjsファイルは実行されません。typescriptで書き直すにはコードが多すぎるため、これは非常に役立ちました。次のコメントコメントの長さのために例を挙げます
Nour Lababidi

私は単にこのコードを次のように使用しました:ngAfterViewInit(){debugger; $ .getScript( "/ assets / js / jquery.app.js"、function(){alert( "Script loaded and execution。"); //ここでは、ロードされたスクリプトで定義したものをすべて使用できます}); }
Nour Lababidi 2018

:角度Iで「$」については、これに続くstackoverflow.com/questions/32050645/...
ヌールLababidi

28

私が使用最近あまり複雑なバージョンをしてjQueryの

<script src="scripts/jquery.js"></script>
<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  var $head = $("head");
  for (var i = 0; i < js.length; i++) {
    $head.append("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

IE6 / 7、Firefox、Safari、Operaでテストしたすべてのブラウザーでうまく機能しました。

更新: jQueryなしバージョン:

<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  for (var i = 0, l = js.length; i < l; i++) {
    document.getElementsByTagName("head")[0].innerHTML += ("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

25
jqueryをロードしようとしているのでない限り、それは素晴らしいことです。

1
将来のリリースでは、jQueryがRequireプラグインをjQuery Coreにロールインする予定です:plugins.jquery.com/project/require
Adam

1
jQueryを使用するさらに良い方法は、を使用すること$.getScriptです。私の答えを見てください。
Muhd、2012

1
Modernizr(yepnope.js)またはlab.jsは、このための適切なソリューションです。重いスクリプトライブラリ(最初にロードする必要があります)を使用することは、モバイルまたは他の多くの状況に最適な答えではありません。
1nfiniti 2012

2
@MaulikGanganiの古いブラウザーとhtmlバリデーターは、スクリプトを終了するためのトークンとしてそれを解釈します。
トラビス

20

基本的にはAdamと同じことを行いましたが、仕事を完了するためにヘッドタグに追加するように少し変更しました。スクリプトとcssファイルの両方を処理するinclude関数(以下のコード)を作成しただけです。

この関数は、スクリプトまたはCSSファイルがまだ動的にロードされていないことも確認します。手動でコード化された値をチェックしないため、より良い方法があったかもしれませんが、目的は果たしました。

function include( url, type ){
    // First make sure it hasn't been loaded by something else.
    if( Array.contains( includedFile, url ) )
        return;

    // Determine the MIME-type
    var jsExpr = new RegExp( "js$", "i" );
    var cssExpr = new RegExp( "css$", "i" );
    if( type == null )
        if( jsExpr.test( url ) )
            type = 'text/javascript';
        else if( cssExpr.test( url ) )
            type = 'text/css';

    // Create the appropriate element.
    var tag = null;
    switch( type ){
        case 'text/javascript' :
            tag = document.createElement( 'script' );
            tag.type = type;
            tag.src = url;
            break;
        case 'text/css' :
            tag = document.createElement( 'link' );
            tag.rel = 'stylesheet';
            tag.type = type;
            tag.href = url;
            break;
    }

    // Insert it to the <head> and the array to ensure it is not
    // loaded again.
    document.getElementsByTagName("head")[0].appendChild( tag );
    Array.add( includedFile, url );
}

そのピクルス以上のコンテキストがないと、私は何の提案もないと思います。上記のコードはそのまま動作し、機能しているプロジェクトから直接取得されました。
10

5
@ palehorse、Mike、Muhdは正しいです。プロジェクトで機能する可能性がありますが、「includedFile」変数と「Array」変数はプロジェクトの他の場所で定義する必要があるため、このコード自体は実行されず、プロジェクトのコンテキスト外でも機能するように編集するか、少なくともそれらの未定義の変数(タイプなど)が何であるかを説明するコメントを追加することをお
勧めします

14

別の素晴らしい答え

$.getScript("my_lovely_script.js", function(){


   alert("Script loaded and executed.");
  // here you can use anything you defined in the loaded script

 });

https://stackoverflow.com/a/950146/671046


2
クロスドメインで機能させるにはどうすればよいですか?(からスクリプトを読み込んでいますhttp://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js
user2284570

9

これが私が見つけたコードの例です...誰かがより良い方法を持っていますか?

  function include(url)
  {
    var s = document.createElement("script");
    s.setAttribute("type", "text/javascript");
    s.setAttribute("src", url);
    var nodes = document.getElementsByTagName("*");
    var node = nodes[nodes.length -1].parentNode;
    node.appendChild(s);
  }

クロスドメインで機能させるにはどうすればよいですか?(からスクリプトを読み込んでいますhttp://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js
user2284570

6

jQueryがすでにロードされている場合は、$ .getScriptを使用する必要があります。

これは、組み込みのコールバック関数があり(依存コードが実行される前にスクリプトがロードされることを保証するため)、キャッシュを制御できるという点で、他の回答よりも優れています。


4

あなたがしたい場合SYNCのスクリプトのロードを、あなたは直接HTML HEADタグにスクリプトのテキストを追加する必要があります。それを追加すると、ASYNCロードがトリガーされます。外部ファイルからスクリプトテキストを同期的に読み込むには、XHRを使用します。簡単なサンプルの下(この記事と他の投稿で他の回答の一部を使用しています):

/*sample requires an additional method for array prototype:*/

if (Array.prototype.contains === undefined) {
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) { if (this[i] === obj) return true; }
    return false;
};
};

/*define object that will wrap our logic*/
var ScriptLoader = {
LoadedFiles: [],

LoadFile: function (url) {
    var self = this;
    if (this.LoadedFiles.contains(url)) return;

    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                self.LoadedFiles.push(url);
                self.AddScript(xhr.responseText);
            } else {
                if (console) console.error(xhr.statusText);
            }
        }
    };
    xhr.open("GET", url, false);/*last parameter defines if call is async or not*/
    xhr.send(null);
},

AddScript: function (code) {
    var oNew = document.createElement("script");
    oNew.type = "text/javascript";
    oNew.textContent = code;
    document.getElementsByTagName("head")[0].appendChild(oNew);
}
};

/*Load script file. ScriptLoader will check if you try to load a file that has already been loaded (this check might be better, but I'm lazy).*/

ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
/*this will be executed right after upper lines. It requires jquery to execute. It requires a HTML input with id "tb1"*/
$(function () { alert($('#tb1').val()); });

3

誰かがより良い方法を持っていますか?

スクリプトを本文に追加する方が、ページの最後のノードに追加するよりも簡単だと思います。これはどう:

function include(url) {
  var s = document.createElement("script");
  s.setAttribute("type", "text/javascript");
  s.setAttribute("src", url);
  document.body.appendChild(s);
}

クロスドメインで機能させるにはどうすればよいですか?(からスクリプトを読み込んでいますhttp://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js
user2284570

3

私はネットで見つけたさらに別のソリューションを使用しました...これはクリエイティブコモンズの下にあり、関数を呼び出す前にソースが含まれていたかどうかをチェックします ...

ここでファイルを見つけることができます:include.js

/** include - including .js files from JS - bfults@gmail.com - 2005-02-09
 ** Code licensed under Creative Commons Attribution-ShareAlike License 
 ** http://creativecommons.org/licenses/by-sa/2.0/
 **/              
var hIncludes = null;
function include(sURI)
{   
  if (document.getElementsByTagName)
  {   
    if (!hIncludes)
    {
      hIncludes = {}; 
      var cScripts = document.getElementsByTagName("script");
      for (var i=0,len=cScripts.length; i < len; i++)
        if (cScripts[i].src) hIncludes[cScripts[i].src] = true;
    }
    if (!hIncludes[sURI])
    {
      var oNew = document.createElement("script");
      oNew.type = "text/javascript";
      oNew.src = sURI;
      hIncludes[sURI]=true;
      document.getElementsByTagName("head")[0].appendChild(oNew);
    }
  }   
} 

クロスドメインで機能させるにはどうすればよいですか?(からスクリプトを読み込んでいますhttp://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js
user2284570

3

YUI 3の優れた機能について知りました(執筆時点でプレビューリリースで利用可能)。YUIライブラリと「外部」モジュール(探しているもの)への依存関係を簡単にコードを追加せずに挿入できます:YUIローダー。。

また、外部モジュールがロードされるとすぐに呼び出される関数に関する2番目の質問にも答えます。

例:

YUI({
    modules: {
        'simple': {
            fullpath: "http://example.com/public/js/simple.js"
        },
        'complicated': {
            fullpath: "http://example.com/public/js/complicated.js"
            requires: ['simple']  // <-- dependency to 'simple' module
        }
    },
    timeout: 10000
}).use('complicated', function(Y, result) {
    // called as soon as 'complicated' is loaded
    if (!result.success) {
        // loading failed, or timeout
        handleError(result.msg);
    } else {
        // call a function that needs 'complicated'
        doSomethingComplicated(...);
    }
});

私にとっては完璧に機能し、依存関係を管理できるという利点があります。YUI 2カレンダーの例については、YUIのドキュメントを参照してください。


これはおそらく、YUIがこの機能だけでわいせつに大きい場合を除いて、理想的です。
Muhd、2012

3

ChromeとSafariに最近組み込まれた、動的インポートと呼ばれる新しいECMA標準が提案されています。

const moduleSpecifier = './dir/someModule.js';

import(moduleSpecifier)
   .then(someModule => someModule.foo()); // executes foo method in someModule

2

仕事で使用する手法は、AJAXリクエストを使用してJavaScriptファイルをリクエストし、次にeval()でリターンすることです。プロトタイプライブラリを使用している場合は、Ajax.Request呼び出しでこの機能をサポートしています。


2

jqueryは.append()関数でこれを解決しました -これを使用して完全なjquery uiパッケージをロードしました

/*
 * FILENAME : project.library.js
 * USAGE    : loads any javascript library
 */
    var dirPath = "../js/";
    var library = ["functions.js","swfobject.js","jquery.jeditable.mini.js","jquery-ui-1.8.8.custom.min.js","ui/jquery.ui.core.min.js","ui/jquery.ui.widget.min.js","ui/jquery.ui.position.min.js","ui/jquery.ui.button.min.js","ui/jquery.ui.mouse.min.js","ui/jquery.ui.dialog.min.js","ui/jquery.effects.core.min.js","ui/jquery.effects.blind.min.js","ui/jquery.effects.fade.min.js","ui/jquery.effects.slide.min.js","ui/jquery.effects.transfer.min.js"];

    for(var script in library){
        $('head').append('<script type="text/javascript" src="' + dirPath + library[script] + '"></script>');
    }

使用するには-jquery.jsをインポートした後、html / php / etcのヘッドにこの1つのファイルを含めるだけで、ライブラリ全体をロードしてヘッドに追加します...

<script type="text/javascript" src="project.library.js"></script>

2

簡潔で、簡潔で、保守しやすいものにしてください!:]

// 3rd party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
    FULL_PATH + 'plugins/script.js'      // Script example
    FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library 
    FULL_PATH + 'plugins/crypto-js/hmac-sha1.js',      // CryptoJS
    FULL_PATH + 'plugins/crypto-js/enc-base64-min.js'  // CryptoJS
];

function load(url)
{
    var ajax = new XMLHttpRequest();
    ajax.open('GET', url, false);
    ajax.onreadystatechange = function ()
    {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4)
        {
            switch(ajax.status)
            {
                case 200:
                    eval.apply( window, [script] );
                    console.log("library loaded: ", url);
                    break;
                default:
                    console.log("ERROR: library not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

 // initialize a single load 
load('plugins/script.js');

// initialize a full load of scripts
if (s.length > 0)
{
    for (i = 0; i < s.length; i++)
    {
        load(s[i]);
    }
}

このコードは、任意の(または指定された)プラットフォームで完全にサポートするために追加の機能を必要とする可能性がある短い機能の例にすぎません。


2

動的モジュールのインポートがFirefox 67以降に導入されました

(async () => {
   await import('./synth/BubbleSynth.js')
})()

エラー処理あり:

(async () => {
    await import('./synth/BubbleSynth.js').catch((error) => console.log('Loading failed' + error))
})()

これは、あらゆる種類の非モジュールライブラリでも機能します。この場合、libはウィンドウオブジェクトで使用できますが、古い方法ですが、オンデマンドでのみ使用できます。

suncalc.jsを使用した例では、サーバーはこの方法で機能するCORSを有効にする必要があります!

(async () => {
 await import('https://cdnjs.cloudflare.com/ajax/libs/suncalc/1.8.0/suncalc.min.js')
 .then(function(){
   let times = SunCalc.getTimes(new Date(), 51.5,-0.1);
   console.log("Golden Hour today in London: " + times.goldenHour.getHours() + ':' + times.sunrise.getMinutes() + ". Take your pics!")
  })
})()

https://caniuse.com/#feat=es6-module-dynamic-import


1

この目的のために特別に設計されたスクリプトがあります。

yepnope.jsはModernizr、lab.jsに組み込まれていますはより最適化されています(ただし、ユーザーフレンドリーではないバージョンです)。

jqueryやプロトタイプなどの大きなライブラリでこれを行うことはお勧めしません。スクリプトローダーの主な利点の1つは、スクリプトを早期にロードできることです。jqueryとすべてのdom要素がロードされるまで待つ必要はありません。スクリプトを動的にロードするかどうかを確認するチェックを実行します。


1

JavaScriptでモジュールスクリプトのインポート/インクルードを自動化する簡単なモジュールを作成しました。それを試してみて、いくつかのフィードバックを惜しまないでください!:)コードの詳細な説明については、このブログ投稿を参照してくださいhttp : //stamat.wordpress.com/2013/04/12/javascript-require-import-include-modules/

var _rmod = _rmod || {}; //require module namespace
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark the root directory of your library, any library


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };

    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

//you can rename based on your liking. I chose require, but it can be called include or anything else that is easy for you to remember or write, except import because it is reserved for future use.
var require = function(script_name) {
    var np = script_name.split('.');
    if (np[np.length-1] === '*') {
        np.pop();
        np.push('_all');
    }

    script_name = np.join('.');
    var uri = _rmod.libpath + np.join('/')+'.js';
    if (!_rmod.loading.scripts.hasOwnProperty(script_name) 
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri, 
            _rmod.requireCallback, 
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};

// ----- USAGE -----

require('ivar.util.array');
require('ivar.util.string');
require('ivar.net.*');

ready(function(){
    //do something when required scripts are loaded
});

1

これらすべてのサンプルで迷子になっていますが、今日、メインの.jsから外部.jsをロードする必要があり、これを行いました。

document.write("<script src='https://www.google.com/recaptcha/api.js'></script>");

あなたはリンクを見ることができます:答え
asmmahmud

1

以下は、コールバックとIEサポートを備えたシンプルなものです。

function loadScript(url, callback) {

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState) { //IE
        script.onreadystatechange = function () {
            if (script.readyState == "loaded" || script.readyState == "complete") {
                script.onreadystatechange = null;
                callback();
            }
        };
    } else { //Others
        script.onload = function () {
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

loadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {

     //jQuery loaded
     console.log('jquery loaded');

});

1

私はここで素晴らしい記事で、私の答えは少し遅れて、この質問についてですけど、www.html5rocks.com - ディープダイブスクリプトのロードの暗い海には

その記事では、ブラウザーのサポートに関して、コンテンツのレンダリングをブロックせずにJavaScriptファイルを動的にロードする最良の方法は次の方法であると結論付けられています。

4つの名前のスクリプトがあることを考えるscript1.js, script2.js, script3.js, script4.js、async = false適用してそれを行うことができます

[
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

今、Specは言う:一緒にダウンロードし、すべてのダウンロードと同時にすぐに実行します。

Firefox <3.6、Operaによると:この「非同期」とは何なのかわかりませんが、JS経由で追加されたスクリプトを追加順に実行します。

Safari 5.0によると、「非同期」は理解できますが、JSで「false」に設定することは理解できません。スクリプトが到着したらすぐに、任意の順序で実行します。

IE <10は言う:「非同期」についての考えありませんが、「onreadystatechange」を使用する回避策があります。

他のすべては言う:私はあなたの友達です、私達は本によってこれをするつもりです。

今、IE <10の完全なコードの回避策:

var scripts = [
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && pendingScripts[0].readyState == 'loaded') {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we’ll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}

後でいくつかのトリックとミニファイ、それは362バイトです

!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
  "//other-domain.com/1.js",
  "2.js"
])

私は上記のアプローチを使用していますが、ChromeとFirefoxで正常に機能していますが、IEブラウザで問題に直面しています
Roshan氏

1

このようなもの...

<script>
     $(document).ready(function() {
          $('body').append('<script src="https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places&callback=getCurrentPickupLocation" async defer><\/script>');
     });
</script>

1

JSファイルをロードする関数の簡単な例を次に示します。関連ポイント:

  • jQueryは必要ないため、最初にこれを使用してjQuery.jsファイルもロードできます。
  • コールバックと非同期です
  • ロードされたURLのレコードでエンクロージャーを保持し、ネットワークの使用を回避するため、ロードは1回だけです。
  • jQueryのに反し$.ajaxたり$.getScript、あなたはCSPとこれの問題を解決し、ナンスを使用することができますunsafe-inline。プロパティを使用するだけscript.nonce
var getScriptOnce = function() {

    var scriptArray = []; //array of urls (closure)

    //function to defer loading of script
    return function (url, callback){
        //the array doesn't have such url
        if (scriptArray.indexOf(url) === -1){

            var script=document.createElement('script');
            script.src=url;
            var head=document.getElementsByTagName('head')[0],
                done=false;

            script.onload=script.onreadystatechange = function(){
                if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
                    done=true;
                    if (typeof callback === 'function') {
                        callback();
                    }
                    script.onload = script.onreadystatechange = null;
                    head.removeChild(script);

                    scriptArray.push(url);
                }
            };

            head.appendChild(script);
        }
    };
}();

今、あなたは単にそれを使う

getScriptOnce("url_of_your_JS_file.js");

1

jsライブラリーのロードに2行以上のコードをとるべきではないと考える人のための、ばかげた1行:P

await new Promise((resolve, reject) => {let js = document.createElement("script"); js.src="mylibrary.js"; js.onload=resolve; js.onerror=reject; document.body.appendChild(js)});

明らかに、インポートしたいスクリプトがモジュールの場合、import(...)関数を使用できます。


1

Promiseを使用すると、このように単純化できます。ローダー機能:

  const loadCDN = src =>
    new Promise((resolve, reject) => {
      if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
      const script = document.createElement("script")
      script.src = src
      script.async = true
      document.head.appendChild(script)
      script.onload = resolve
      script.onerror = reject
    })

使用法(非同期/待機):

await loadCDN("https://.../script.js")

使用法(約束):

loadCDN("https://.../script.js").then(res => {}).catch(err => {})

注:1つの同様のソリューションがありましたが、スクリプトが既にロードされているかどうかはチェックされず、毎回スクリプトがロードされます。これはsrcプロパティをチェックします。


0

jscript、prototype、YUIなどの主要なjavascriptライブラリはすべて、スクリプトファイルのロードをサポートしています。たとえば、YUIでは、コアをロードした後、以下を実行してカレンダーコントロールをロードできます。

var loader = new YAHOO.util.YUILoader({

    require: ['calendar'], // what components?

    base: '../../build/',//where do they live?

    //filter: "DEBUG",  //use debug versions (or apply some
                        //some other filter?

    //loadOptional: true, //load all optional dependencies?

    //onSuccess is the function that YUI Loader
    //should call when all components are successfully loaded.
    onSuccess: function() {
        //Once the YUI Calendar Control and dependencies are on
        //the page, we'll verify that our target container is 
        //available in the DOM and then instantiate a default
        //calendar into it:
        YAHOO.util.Event.onAvailable("calendar_container", function() {
            var myCal = new YAHOO.widget.Calendar("mycal_id", "calendar_container");
            myCal.render();
        })
     },

    // should a failure occur, the onFailure function will be executed
    onFailure: function(o) {
        alert("error: " + YAHOO.lang.dump(o));
    }

 });

// Calculate the dependency and insert the required scripts and css resources
// into the document
loader.insert();

あなたはリンクを見ることができます:答え
asmmahmud

0

上記の投稿の一部を実際の例で調整しました。ここでは、CSSとJSを同じ配列で指定することもできます。

$(document).ready(function(){

if (Array.prototype.contains === undefined) {
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) { if (this[i] === obj) return true; }
    return false;
};
};

/* define object that will wrap our logic */
var jsScriptCssLoader = {

jsExpr : new RegExp( "js$", "i" ),
cssExpr : new RegExp( "css$", "i" ),
loadedFiles: [],

loadFile: function (cssJsFileArray) {
    var self = this;
    // remove duplicates with in array
    cssJsFileArray.filter((item,index)=>cssJsFileArray.indexOf(item)==index)
    var loadedFileArray = this.loadedFiles;
    $.each(cssJsFileArray, function( index, url ) {
            // if multiple arrays are loaded the check the uniqueness
            if (loadedFileArray.contains(url)) return;
            if( self.jsExpr.test( url ) ){
                $.get(url, function(data) {
                    self.addScript(data);
                });

            }else if( self.cssExpr.test( url ) ){
                $.get(url, function(data) {
                    self.addCss(data);
                });
            }

            self.loadedFiles.push(url);
    });

    // don't load twice accross different arrays

},
addScript: function (code) {
    var oNew = document.createElement("script");
    oNew.type = "text/javascript";
    oNew.textContent = code;
    document.getElementsByTagName("head")[0].appendChild(oNew);
},
addCss: function (code) {
    var oNew = document.createElement("style");
    oNew.textContent = code;
    document.getElementsByTagName("head")[0].appendChild(oNew);
}

};


//jsScriptCssLoader.loadFile(["css/1.css","css/2.css","css/3.css"]);
jsScriptCssLoader.loadFile(["js/common/1.js","js/2.js","js/common/file/fileReader.js"]);
});

0

ワンライナーを愛するあなたのために:

import('./myscript.js');

次のようなエラーが発生する可能性があります。

元の「http://127.0.0.1」からの「http://..../myscript.js」にあるスクリプトへのアクセスがCORSポリシーによってブロックされました:「Access-Control-Allow-Origin」ヘッダーが存在しません要求されたリソース。

その場合、次のようにフォールバックできます。

fetch('myscript.js').then(r => r.text()).then(t => new Function(t)());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.