Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Мне кажется это смешивание системы модулей и загрузчика модулей в одно целое. Более того, не самое удачное.Вы ошибатесь. Загрузчик — это всего лишь обычный, ни чем ни лучше других, модуль в модульной системе. Сама модульная система знает только про модули и разрешение зависимостей между ними, ничего более. Модуль-загрузчик приведен лишь в качестве примера, иллюстрирующего случай, когда нужен асинхронный провайд модуля.
Но никто не мешает сделать тоже самое с AMDМожете привести пример кода для AMD, иллюстрирующего модуль, которые экспортирует класс, который наследуется от класса из API Яндекс.Карт? Тот же пример, который в статье разобран.
Далее, у меня мнение, что система модулей должна быть статически анализируема.А что в YM этому сейчас препятствует? В этом плане он ничем не отличается ни от CommonJs, ни от AMD.
Можете привести пример кода для AMD, иллюстрирующего модуль, которые экспортирует класс, который наследуется от класса из API Яндекс.Карт? Тот же пример, который в статье разобран.
config.hosts.ymaps + '/2.1.4/?lang=ru-RU&load=package.full&coordorder=longlat&format=AMD' отдается AMD модуль.А что в YM этому сейчас препятствует? В этом плане он ничем не отличается ни от CommonJs, ни от AMD.
По URL config.hosts.ymaps + '/2.1.4/?lang=ru-RU&load=package.full&coordorder=longlat&format=AMD' отдается AMD модуль.Как это помогает, в плане асинхронности, наследованию моего модуля от класса, предоставляемого из апи? Приведите пример описания модуля ComplexLayer для AMD из статьи.
Нельзя ответить на вопрос «когда?».А зачем на него отвечать для статического анализа кода?
Как это помогает, в плане асинхронности, наследованию моего модуля от класса, предоставляемого из апи? Приведите пример описания модуля ComplexLayer для AMD из статьи.
Вы указываете в конфигурации AMD-загрузчика, что модуль ymaps находится под таким URL (map.yandex.ru/api/...) потом ComplexLayer просто его указывает в зависимостях и использует (прям как у вас в коде).А вам не кажется, что это усложнение модульной системы? Более того тут есть нарушение принципов модульности, так как помимо самого модуля, мне еще что-то куда-то нужно дописывать.
define('ymaps', function() {
return loadYMapsAndInitAndReturnPromise();
});
define('ComplexLayer', ['inherit', 'ymaps'], function(inherit, ymaps) {
return ymap
.then(
function(api) {
return inherit(api.Layer, ...);
},
function(err) {
if (err.isFlashBlocked) {
showNotification("please disable flashblocker or something...");
} else {
...
}
});
});
YMapAPI.prototype.something = function() {
return this.ready().then(function(api) { ... });
}
var complexLayer = new ComplexLayer();
я должен так и писать, а не делать странные вещи типа:var complexLayerPromise = ComplexLayerClassPromise.then(function(ComplexLayer) {
return new ComplexLayer;
});
выглядит так, как будто автор не делал анализ существующих решений.Все модульные системы из статьи (CommonJS, AMD) я использую и использовал (собственно, для NodeJs алльтернативы CommonJS и нет), и именно из-за их недостатков была и сделана YM, а не потому что надо было сделать очередное «свое». Если бы хоть одна отвечала нашим потребностям, я бы никогда не стал писать свое.
// Foo.js
include
.js('./Baz.js')
.done(function(resp){
alert(resp.Baz);
});
// Baz.js
var resource = include,
resume = include.pause();
setTimeout(function(){
resource.exports = 'Baz';
resume();
}, 5000);
module.exports = new Promise(...)
require.define('A', function() {
var module = this;
setTimeout(function() {
module.exports = 'A';
module.ready(); // сообщаем о том, что модуль готов
});
});
require.define('B', ['A'] function() { // Функция вызовется при загрузке всех зависимостей
// Если в this.ready передан callback,
// модуль будет считаться готовым только после его выполнения...
this.ready(function (moduleA) {
// ...а он выполнится только после готовности всех зависимостей
this.exports = moduleA + 'B';
});
});
Т.е. если передался промис — ждем его выполнения, в противном случае отдаем все сразу.
// Асинхронная инициализация
require.define('A', function() {
var module = this;
setTimeout(function() {
module.exports = 'A';
module.ready(); // сообщаем о том, что модуль готов
});
// Если ничего не вернули - ждем вызова module.ready();
});
// Синхронная инициализация
require.define('B', function() {
module.exports = 'B';
return module;
// return true; module.ready(); return module.exports - можно реализовать любой подходящий вариант,
// который однозначно обработается
});
require.define('C', ['A', 'B'] function() {
// Здесь мы имеем возможность начать инициализацию до готовности зависимостей (если они нам тут не нужны),
// что позволяет быстрее проинициализировать все модули.
this.ready(function (moduleA, moduleB) {
// Но нам все равно нужен callback, в который оповестит о готовности.
this.exports = moduleA + moduleB + 'C';
// return module; return true; module.ready(); return module.exports - если на этом этапе модуль готов.
// Иначе выполняем необходимые асинхронные действия и вызываем module.ready() по их завершению.
});
});
define([], function () {
return {
load: function (name, req, onload, config) {
req([name], function (module) {
module.ready(function () {
onload(module);
});
});
}
};
});
define([], function () {
var callbacks = [];
setTimeout(function () {
for (var i = 0; i < callbacks.length; i++) {
callbacks[i]();
}
}, 5000);
return {
// ...
someApiMethod: function () {
// ...
},
ready: function (callback) {
callbacks.push(callback);
})
};
});
define(['loader!asyncModule'], function (am) {
am.someApiMethod();
});
define(['asyncModule'], function (am) {
return {
someMethod: function () {
// blah blah
},
someOtherMethod: function () {
// fdsfds
am.someApiMethod();
// burp
}
};
});
require.config({
paths: {
'raw/asyncModule': 'asyncModule'
},
map: {
'*': {
'asyncModule': 'loader!raw/asyncModule'
}
},
deps: ['myModule'],
callback: function (myModule) {
myModule.someMethod();
myModule.someOtherMethod();
}
});
define(['module'], function (module) {
var config = module.config();
return {
load: function (name, req, onload) {
// Можно использовать любой другой способ загрузки
req(config.hosts.ymaps + '/2.1.4/?lang=ru-RU&load=package.full&coordorder=longlat', function() {
ymaps.ready(function() {
onload(ymaps);
});
});
}
};
});
define(['ymaps!'], function (ymaps) {
ymaps.someApiMethod();
});
function() { load.apply(this, arguments); } эквивалентна просто load?curl(['js!nonAMD.js'])
.next(['dep1', 'dep2', 'dep3'], function (dep1, dep2, dep3) {
// do something before the dom is ready
})
.next(['domReady!'])
.then(
function () {
// do something after the dom is ready
},
function (ex) {
// show an error to the user
}
);
Модульная система YM