Пакет инструментальных программ JavaScript Dojo – это отличная библиотека, удовлетворяющая большинство требований к созданию функционально насыщенных интернет-приложений. Однако при определенных обстоятельствах для специализированных приложений могут понадобиться внешние JavaScript-библиотеки. В этом случае можно добавить библиотеку к приложению с помощью стандартного для HTML способа – дополнительного тега <script>, однако это чревато снижением производительности приложения. К счастью, Dojo предоставляет альтернативу этому способу – dojo.io.script.
В этой статье рассматриваются преимущества и недостатки использования dojo.io.script. Приведенный пример исходного кода демонстрирует, как избежать наиболее опасных ловушек. Используемый в статье исходный код можно загрузить по данной ссылке.
Два метода загрузки внешних JavaScript-библиотек
В таблице 1 сравниваются два метода загрузки внешних JavaScript-библиотек.
Таблица 1. Тег <script> и dojo.io.script
| Тег <script> | dojo.io.script | |
|---|---|---|
| Влияние на скорость загрузки страниц | Потенциально значительное; загрузка библиотеки блокирует начало работы страницы. | Отсутствует; библиотека загружается по требованию. |
| Влияние на скорость выполнения кода | Отсутствует. | При первоначальном использовании будет задержка на время загрузки библиотеки. |
| Уровень сложности | Простой. Весь код может использовать библиотеку немедленно. | Сложный. Код должен грамотно отправить запрос и ждать окончания загрузки библиотеки. |
Метод dojo.io.script обеспечивает явные преимущества приложениям, использующим внешнюю библиотеку только в отдельном ответвлении кода. Особенно выгодна отложенная загрузка. Метод с использованием тега <script> имеет серьезное преимущество, заключающееся в простоте использования библиотеки в приложении. Имеет смысл рассмотреть использование dojo.io.script, поскольку он при любых обстоятельствах обеспечивает лучшую скорость загрузки страниц.
В листинге 1 приведен простой пример использования dojo.io.script для
асинхронной загрузки одной библиотеки.
Листинг 1. Одиночный вызов dojo.io.script
dojo.require("dojo.io.script");
dojo.addOnLoad(function() {
// Загрузить библиотеку.
// dojo.io.script.get является асинхронным, возвращается объект dojo.Deferred
var deferred = dojo.io.script.get({url : "url_of_library.js"});
// Обработка отложенного обратного вызова
deferred.then(function() {
// Эта функция вызывается, когда библиотека успешно загружается
// Здесь необходимо вставить код приложения, зависящий от библиотеки
}, function() {
// Эта функция вызывается при возникновении ошибки
});
});
|
В случае использования библиотек, имеющих несколько модулей с межмодульными зависимостями, для достижения нужного поведения при загрузке могут понадобиться последовательные вызовы, аналогичные приведенным выше. В листинге 2 показан более сложный пример с последовательными вызовами.
Листинг 2. Последовательные вызовы dojo.io.script
dojo.require("dojo.io.script");
dojo.addOnLoad(function() {
// Загрузка JavaScript-библиотеки, состоящей из двух модулей
// Мы создаем частичную функцию загрузки второго модуля;
// Это упрощает code path
var deferred = dojo.io.script.get({url : "url_of_first_module.js"})
.then(dojo.hitch(dojo.io.script, 'get', {url : "url_of_second_module.js"}));
// Отложенная обработка выполняется здесь
});
|
При загрузке мультимодульных библиотек с использованием dojo.io.script или при использовании библиотек в нескольких местах исходного кода управление dojo.io.script и получаемыми отложенными объектами может стать сложным. Основным вопросом использования библиотеки в нескольких местах является гарантия однократной загрузки модуля.
При загрузке мультимодульных библиотек или при использовании библиотеки в нескольких местах рассмотрите возможность применения промежуточных методов.
Метод libproxy управляет межмодульными зависимостями и гарантирует однократную загрузку этих модулей. Пример использования libproxy приведен в листинге 3.
Листинг 3. Использование libproxy (libproxy_example.html)
dojo.require("proxy.jsv");
dojo.addOnLoad(function() {
var jsvProxy = new proxy.jsv();
jsvProxy.load('json-schema-draft-01').then(function() {
// Здесь загружается JSV-модуль проверки совместимости с draft 1.
alert("loaded JSV draft 1");
});
});
|
В листинге 4 показано, как использовать libproxy для упаковки процедуры загрузки библиотеки Гэри Курта JSON Schema Validator (JSV).
Листинг 4. Упаковка загрузки библиотеки JSV (proxy/jsv.js)
dojo.provide("proxy.jsv");
dojo.require("com.ibm.developerworks.libproxy");
/**
*
*/
dojo.declare("proxy.jsv", [com.ibm.developerworks.libproxy], {
/**
* В этом файле мы определяем структуру нашей библиотеки
* и ее межмодульные зависимости
*/
constructor : function() {
var jsvRoot = "https://raw.github.com/garycourt/JSV/master/lib";
this.modules = {
'_uri' : {
sources : [{url : jsvRoot + "/uri/uri.js"}]
},
'base' : {
sources : [{url : jsvRoot + "/jsv.js"}],
deps : ['_uri']
},
'json-schema-draft-01' : {
sources : [{url : jsvRoot + "/json-schema-draft-01.js"}],
deps: ['base']
},
'json-schema-draft-02' : {
sources : [{url : jsvRoot + "/json-schema-draft-02.js"}],
deps: ['base']
},
'json-schema-draft-03' : {
sources : [{url : jsvRoot + "/json-schema-draft-03.js"}],
deps: ['base']
}
};
}
});
|
В листинге 5 показан исходный код libproxy.
Листинг 5. Базовая реализация для упаковки библиотеки (com/ibm/developerworks/libproxy.js)
dojo.provide("com.ibm.developerworks.libproxy");
dojo.require("dojo.io.script");
dojo.require("dojo.DeferredList");
/**
* Не используйте этот класс напрямую; расширьте его
* и переопределите поле modules в конструкторе
*/
dojo.declare("com.ibm.developerworks.libproxy", [], {
constructor : function() {
this._moduleDeferreds = [];
},
/**
* Хранит модули библиотеки (и ссылки на их зависимости,
* если они есть).
*
* NB: массивы 'sources' и 'deps' будут загружаться одновременно.
* Если нужно сериализировать этот процесс, добавьте еще один уровень модулей,
* т.е. uri.js ДОЛЖЕН быть загружен до jsv.js
*
* Массив 'sources' содержит объекты, передаваемые в полном объеме
* в dojo.io.script.get()
*
* Пример, { 'module1Ref': { sources: [{ url: "module1.js" }] },
* 'module2Ref': { sources: [{ url: "module2.js" }], deps: ['module1'] } };
*/
modules : null,
/**
* Возвращает объект dojo.Deferred, методы callback/errback которого
* активизируются по готовности модуля к использованию.
* Последовательность обратных вызовов будет содержать ссылку на модуль.
*
* Пример использования: load('module2').then(function() {});
*/
load : function(/* String */moduleRef) {
var F = this.declaredClass + ".";
console.debug(F + "load()", arguments);
// Проверка кэша - загружался ли этот модуль библиотеки ранее?
if (this._moduleDeferreds[moduleRef]) {
return this._moduleDeferreds[moduleRef];
}
// Создать новый deferred и поместить в кэш
var deferred = this._moduleDeferreds[moduleRef] = new dojo.Deferred();
var module = this.modules[moduleRef];
if (module) {
deferred.callback(moduleRef);
if (module.deps) {
// Параллельно загрузить зависимости
deferred = deferred.then(dojo.hitch(this,
function(/* Array */dependencies) {
var defs = dojo.map(dependencies, dojo.hitch(this,
'load'));
return new dojo.DeferredList(defs, false, true);
}, module.deps));
}
// Параллельно загрузить исходники
deferred = deferred.then(dojo.hitch(this,
function(/* Array */sources) {
var defs = dojo.map(sources, dojo.hitch(dojo.io.script,
'get'));
return new dojo.DeferredList(defs, false, true);
}, module.sources));
} else {
deferred.errback("Unknown module reference.");
}
return deferred;
}
});
|
Длительная загрузка страниц при использовании нескольких инструментальных JavaScript-пакетов может быстро превратиться в проблему. В статье рассматривался подход, альтернативный подходу с использованием тегов <script>. Для ускорения времени загрузки страниц можно использовать функциональность dojo.io.script, загружая библиотеки "отложенным" способом. Для упрощения реализации этого подхода можно использовать libproxy в качестве промежуточного уровня, управляющего зависимостями и загрузкой.
| Описание | Имя | Размер | Метод загрузки |
|---|---|---|---|
| Пример, упаковка JSV-библиотеки с помощью libproxy | sample.zip | 4 КБ | HTTP |
Научиться
- Оригинал статьи: Load external JavaScript libraries on demand with Dojo 1.5 (EN).
- Программный интерфейс Dojo для dojo.io.script: дополнительная информация об этом объекте.
- Документация по dojo.io.script: дополнительная информация по dojo.io.script.
-
JSV: дополнительная информация о замечательной JSV-библиотеке Гарри Курта (Gary Court).
- developerWorks в Твиттере. Следите за твитами developerWorks.
Обсудить
-
Принимайте участие в
форумах на
developerWorks Россия.
Ник Мейнард (Nick Maynard) работает в группе Business Solutions Team подразделения IBM Software Lab в Херсли (Великобритания). Специализируется на Dojo, Ajax, Web-программировании, Web-сервисах и Linux. Связаться с ним можно по адресу nick.maynard@uk.ibm.com.