Loading javascript asynchronously - How to execute callbacks?

I am creating a javascript widget that needs to load asynchronously.

The problem is that there can be more than one of these widgets on this page and that the widget must be initialized by sending it an array of parameters via {}.

What's the best way to do this? I've heard that just setting onload or onreadystatechange doesn't work in all browsers.

I checked the digg widget but I can't figure out what they are doing, can anyone take a look at this?

Here are some of their code:

(function () {
var s, s1, diggWidget = {
    id: "digg-widget-1282651415272",
    width: 300,
    display: "tabbed"
};
if (window.DiggWidget) {
    if (typeof DiggWidget == 'function') {
        new DiggWidget(diggWidget);
    } else {
        DiggWidget.push(diggWidget);
    }
} else {
    DiggWidget = [diggWidget];
    s = document.createElement('SCRIPT');
    s.type = 'text/javascript';
    s.async = true;
    s.src = 'http://widgets.digg.com/widgets.js';
    s1 = document.getElementsByTagName('SCRIPT')[0];
    s1.parentNode.insertBefore(s, s1);
}
})();

      

So, if DiggWidget is already available (downloaded earlier due to multiple instances), it creates a new widget if the DiggWidget function is a function, otherwise the DiggWidget is used as an array and the current settings are clicked on it.

First, why has DiggWidget always been a function?

If the widget is the only one (or the first), the script tag is added asynchronously, no callbacks are defined.

Then looking at widgets.js they do this:

At the top:

(function () {
var A;
if (window.DiggWidget) {
    if (typeof DiggWidget != "function") {
        A = DiggWidget
    } else {
        return
    }
}

      

Down below:

    if (A) {
    while (A.length) {
        new DiggWidget(A.shift())
    }
}

      

Now I don't quite understand it. Is DiggWidget (array) available for this .js? It's in an anonymous function. So if I run a script like this two times, won't DiggWidget be a new instance every time?

Or am I completely wrong? Sorry if yes. If there are better methods for a callback with multiple script instances please tell me.

+1


source to share


1 answer


First, why has DiggWidget always been a function?

It will become a function when the asynchronous script loads and executes

Is DiggWidget (array) available for this .js

Yes, it window.DiggWidget

is global, so it is available for this script.

The way the widget works is pretty simple.

If the DiggWidget

script parameter hasn't been loaded yet, it window.DiggWidget

won't be a function. Initially it will be undefined variable, so else block

} else {
    DiggWidget = [diggWidget];

      

executes and defines it as an array. From now on until the script widget is loaded, it will be defined as an array.

Now, while the DiggWidget

script is loading asynchronously, keep pushing all initialization objects {..}

onto the array with the same name - window.DiggWidget

.



When the script is loaded, before it catches up with the global variable DiggWidget

, it sees the objects in that array and safely writes it somewhere else. It then takes the name of the DiggWidget, walks through each object, and initializes the widget for each.

Here's the complete embed code, annotated with comments.

User code

(function () {
var s, s1, diggWidget = {
    id: "digg-widget-1282651415272",
    width: 300,
    display: "tabbed"
};
// either the external widget script has already loaded, or there is more than
// one widget to be embedded on the page, and the previous widget embed code
// defined this variable
if (window.DiggWidget) {
    // the external widget script has been loaded asynchronously 
    // because DiggWidget is a function. Can directly create a new object.
    if (typeof DiggWidget == 'function') {
        new DiggWidget(diggWidget);
    }
    // a previous widget embed code defined this global array. Remember the
    // widgets initialization settings for when the external script loads.
    else {
        DiggWidget.push(diggWidget);
    }
}
// the external widget script has not loaded yet and
// this is the first widget ever to be embedded on the page
else {
    // DiggWidget does not exist at this point. So make it an array
    // and store the first widget config object in it
    DiggWidget = [diggWidget];
    s = document.createElement('SCRIPT');
    s.type = 'text/javascript';
    s.async = true;
    s.src = 'http://widgets.digg.com/widgets.js';
    s1 = document.getElementsByTagName('SCRIPT')[0];
    s1.parentNode.insertBefore(s, s1);
}
})();

      

Widget code (top)

(function () {
var A;
// global DiggWiget is defined. it will either be an array if 
// the widget code hasn't loaded yet, or a function if it has
if (window.DiggWidget) {
    // it an array, so keep that array somewhere safe
    // because we are gonna take over the DiggWidget variable purdy soon
    if (typeof DiggWidget != "function") {
        A = DiggWidget
    }
    // window.DiggWidget must be a function
    // there is no widget to initialize, just return
    else {
        return
    }
}

      

(down below)

    // A is the array of widget settings we backed up a little earlier
    if (A) {
    // loop through each config object and create the actual
    // widget object
    while (A.length) {
        new DiggWidget(A.shift())
    }
}

      

+6


source







All Articles