Загрузка JavaScript асинхронно - Как сделать обратные вызовы? - PullRequest
1 голос
/ 24 августа 2010

Я создаю виджет JavaScript, который должен загружаться асинхронно.

Проблема в том, что на странице может быть более одного из этих виджетов и что виджет должен быть инициализирован путем отправки ему массива параметров через {}.

Каков наилучший способ сделать это?Я слышал, что простая настройка onload или onreadystatechange работает не во всех браузерах.

Я проверил виджет digg, но я не могу понять, что они делают, может кто-нибудь взглянуть на это?

Вот некоторые из их кода:

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

Итак, если DiggWidget уже доступен (загружен ранее из-за нескольких экземпляров), он создает новый виджет, если DiggWidget является функцией, в противном случаеDiggWidget используется в качестве массива, и текущие настройки помещаются в него.

Во-первых, зачем DiggWidget быть функцией?

Если виджет является единственным (или первым), тег сценария добавляется асинхронно, обратные вызовы не определяются.

Затем, глядя на widgets.js, они делают это:

Вверху:

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

Внизу:

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

Теперь я невполне понимаю это.Доступен ли DiggWidget (массив) для этого .js?Это в анонимной функции.Так что, если я включу такой скрипт дважды, не будет ли DiggWidget каждый раз новым экземпляром?

Или я совершенно не прав в этом?Извините если так.Если есть более эффективные методы для обратного вызова с несколькими экземплярами сценария, пожалуйста, сообщите.

1 Ответ

6 голосов
/ 24 августа 2010

Во-первых, почему DiggWidget будет когда-либо функцией?

Она станет функцией, когда асинхронный скрипт загружает и выполняет

Является ли DiggWidget (массив), доступный для этого .js

Да, window.DiggWidget является глобальным, поэтому он доступен для этого сценария.

Способ работы виджета довольно прост.

Если скрипт DiggWidget еще не загружен, то window.DiggWidget не будет функцией.Первоначально это будет неопределенная переменная, поэтому блок else

} else {
    DiggWidget = [diggWidget];

выполняется и определяет его как массив.Отныне и до загрузки скрипта виджета он будет определяться как массив.

Теперь, пока скрипт DiggWidget не загружается асинхронно, продолжайте помещать все объекты инициализации {..} в массив с тем же именем -window.DiggWidget.

Когда скрипт загружается, перед тем как он обгонит глобальную переменную DiggWidget, он видит объекты в этом массиве и безопасно записывает его где-то еще.Затем принимает имя DiggWidget, проходит по каждому объекту и инициализирует виджет для каждого.

Вот полный код для вставки с комментариями.

Код пользователя

(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's 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's 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's 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);
}
})();

Код виджета (вверху)

(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's 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
    }
}

(внизу)

    // 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())
    }
}
...