Javascript 异步脚本加载回调

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12820953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 08:34:05  来源:igfitidea点击:

Asynchronous Script Loading Callback

javascriptfunctionasynchronouscallback

提问by James Kyle

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

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

I've created a short function based on Mathias Bynens Optimization of the Google Analytics asynchronous scriptthat goes as following:

我创建了一个基于谷歌分析异步脚本的 Mathias Bynens 优化的简短函数,如下所示:

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);
}

This works great and I've already started using it for several different scripts

这很好用,我已经开始将它用于几个不同的脚本

// 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');?

The problem comes when I encounter a script that needs to be called after it's loaded:

当我遇到一个需要在加载后调用的脚本时,问题就来了:

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

So I figured I'd turn this into a callback function that would be used as so:

所以我想我会把它变成一个回调函数,可以这样使用:

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

I did not expect that this would be difficult for me to do but it has turned out that way.

我没想到这对我来说很难做到,但结果就是这样。

My question is what is the most efficient way to add a callback without overcomplicating the code.

我的问题是在不使代码过于复杂的情况下添加回调的最有效方法是什么。

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

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

回答by James Kyle

Thanks RASGfor https://stackoverflow.com/a/3211647/982924

感谢RASG提供https://stackoverflow.com/a/3211647/982924

Async function with callback:

带回调的异步函数:

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);
}

Usage:

用法:

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

jsFiddle

js小提琴

回答by Ced

A more recent snippet:

最近的一个片段:

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);
    });
}

utilisation

利用率

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


James Kyle's answerdoesn't take IE9 into account. Here is a modified version of the code I found in the link proposed in the comments. Modify the var baseUrl so it can find the script accordingly.

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);
}

utilisation:

用途:

loadAsync('https://www.gstatic.com/charts/loader.js' , function(){
    chart.loadCharts();
    });
// OR relative path
loadAsync('fastclick.js', null, true);

回答by Fredrik

The other answers works well, but aren't super readable or require Promises. Here is my two cents:

其他答案效果很好,但不是超级可读或需要承诺。这是我的两分钱:

function loadScript(src, callback) {
    var script = document.createElement('script');
    script.setAttribute('src', src);
    script.addEventListener('load', callback);
    document.head.appendChild(script);
},