31

http://jsfiddle.net/JamesKyle/HQDu6/

Mathias Bynens Optimization of the Google Analytics 非同期スクリプトに基づいて、次のような短い関数を作成しました。

function async(src) {
  var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
  o.src = '//' + src;
  s.parentNode.insertBefore(o, s);
}

これはうまく機能し、すでにいくつかの異なるスクリプトで使用し始めています

// Crazy Egg
async('dnn506yrbagrg.cloudfront.net/pages/scripts/XXXXX/XXXXX.js?' + Math.floor(new Date().getTime() / 3600000));

// User Voice
var uvOptions = {};
async('widget.uservoice.com/XXXXX.js');

// Google Analytics
var _gaq = [['_setAccount', 'UA-XXXXX-XX'], ['_setDomainName', 'coachup.com'], ['_trackPageview']];
async('google-analytics.com/ga.js');

// Stripe
async('js.stripe.com/v1');​

問題は、ロード後に呼び出す必要があるスクリプトに遭遇したときに発生します。

// Snap Engage
async('snapabug.appspot.com/snapabug.js');
SnapABug.init('XXXXX-XXXXX-XXXXX-XXXXX-XXXXX');

だから私はこれを次のように使用されるコールバック関数に変えると考えました:

async('snapabug.appspot.com/snapabug.js', function() {
    SnapABug.init('XXXXX-XXXXX-XXXXX-XXXXX-XXXXX');
});

これが私にとって難しいことだとは思っていませんでしたが、そのようになりました。

私の質問は、コードを過度に複雑にすることなくコールバックを追加する最も効率的な方法は何かということです。

jsfiddle を参照してください: http://jsfiddle.net/JamesKyle/HQDu6/

4

3 に答える 3

57

https://stackoverflow.com/a/3211647/982924のRASGに感謝します。

コールバックを伴う非同期関数:

function async(u, c) {
  var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
  o.src = '//' + u;
  if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
  s.parentNode.insertBefore(o, s);
}

使用法:

async('snapabug.appspot.com/snapabug.js', function() {
    SnapABug.init('XXXXX-XXXXX-XXXXX-XXXXX-XXXXX');
});

jsフィドル

于 2012-10-10T14:17:02.783 に答える
13

より最近のスニペット:

async function loadAsync(src) {
    const script = document.createElement('script');
    script.src = src;
    return new Promise((resolve, reject) => {
        script.onreadystatechange = function () {
            if (script.readyState === 'loaded' || script.readyState === 'complete') {
                script.onreadystatechange = null;
                resolve(true);
            }
        };
        document.getElementsByTagName('head')[0].appendChild(script);
    });
}

利用

  loadAsync(`https://....js`).then(_ => {
    //  ... script loaded here
  })

James Kyle の回答では、IE9 が考慮されていません。これは、コメントで提案されたリンクで見つけたコードの修正版です。それに応じてスクリプトを見つけられるように、var baseUrl を変更します。

//for requiring a script loaded asynchronously.
function loadAsync(src, callback, relative){
    var baseUrl = "/resources/script/";
    var script = document.createElement('script');
    if(relative === true){
        script.src = baseUrl + src;  
    }else{
        script.src = src; 
    }

    if(callback !== null){
        if (script.readyState) { // IE, incl. IE9
            script.onreadystatechange = function() {
                if (script.readyState === "loaded" || script.readyState === "complete") {
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else {
            script.onload = function() { // Other browsers
                callback();
            };
        }
    }
    document.getElementsByTagName('head')[0].appendChild(script);
}

利用:

loadAsync('https://www.gstatic.com/charts/loader.js' , function(){
    chart.loadCharts();
    });
// OR relative path
loadAsync('fastclick.js', null, true);
于 2016-05-11T08:50:39.687 に答える
9

他の回答はうまく機能しますが、非常に読みやすく、約束を必要としません。ここに私の2セントがあります:

function loadScript(src, callback) {
    var script = document.createElement('script');
    script.setAttribute('src', src);
    script.addEventListener('load', callback);
    document.head.appendChild(script);
},
于 2019-04-13T21:40:44.003 に答える