#javascript #dojo #ibm-connections
#javascript #dojo #ibm-connections
Вопрос:
У меня есть iWidget, разработанный для IBM Connections, и мой код javascript зависит от Dojo (который по умолчанию включен в Connections).
В настоящее время он работает в Connections 4.0 и 4.5, но не работает в Connections 5.0 (выпущен на прошлой неделе), поскольку Dojo был обновлен до версии v1.9 и жалуется на мое использование dojo.require
.
Эти сообщения появляются в консоли браузера, когда мой виджет пытается загрузиться в Connections 5.0:
Избегайте вызова dojo.require() для загрузки классов во время выполнения, используйте вместо этого net.jazz.ajax.xdloader.load_async(). Функции '(анонимной)' требуется класс 'dojox.atom.io.model'. Избегайте вызова dojo.require() для загрузки классов во время выполнения, используйте вместо этого net.jazz.ajax.xdloader.load_async(). Для функции '(анонимной)' требуется класс 'dojox.atom.io.Connection'.
Я хочу создать условный код, который использует разные способы определения моего класса виджетов и требует других модулей Dojo в зависимости от версии Dojo.
Виджет javascript в настоящее время выглядит следующим образом:
dojo.provide('insightCommunityWidgetClass');
dojo.require('dojox.atom.io.model');
dojo.require('dojox.atom.io.Connection');
dojo.declare('insightCommunityWidgetClass',null,{
// Class fields and methods. Currently 680 lines uncompressed.
});
Я еще не создал версию, которая работает с Dojo 1.9 / Connections 5.0, но я думаю, что это выглядело бы примерно так (и мне нужно, чтобы имя моего файла javascript соответствовало желаемому имени класса):
define(['dojo/_base/declare','dojox.atom.io.model','dojox.atom.io.Connection'], function(declare){
return declare(null, {
// Class fields and methods.
});
});
Как я могу поместить оба этих файла в один файл и выбирать между ними, не дублируя тело класса?
Обновить:
Я попробовал некоторый условный код, проверяя (define amp;amp; define.amd)
, как предложил Дмитрий, протестировал это на подключениях 4.0 и 4.5, и получаю очень странное поведение.
Временно игнорируя любые попытки не дублировать мой класс, вот некоторый условный код, который я использовал точно так, как показано, с сильно уменьшенным классом виджетов:
if (define amp;amp; define.amd) {
console.log('Declaring insightWidgetClass with AMD (new method).');
define(['dojo/_base/declare','dojox/atom/io/model','dojox/atom/io/Connection'],
function(declare){
return declare(null,{
SVC_INV: 1,
onLoad: function() {
console.log('insightWidgetClass onLoad.');
}
});
}
);
} else {
console.log('Declaring insightWidgetClass with dojo.declare (old method).');
dojo.provide('insightWidgetClass');
dojo.require('dojox.atom.io.model');
dojo.require('dojox.atom.io.Connection');
dojo.declare('insightWidgetClass',null,{
SVC_INV: 1,
onLoad: function() {
console.log('insightWidgetClass onLoad.');
}
});
}
Похоже, это вообще не выполняется. Ни одно из моих console.log
сообщений не отображается в консоли браузера.
Если я закомментирую условные обозначения и сделаю так, чтобы единственным активным кодом был блок после else
, он запускается. Я получаю «объявление … (старый метод)» и консольные сообщения «insightWidgetClass onLoad».
Я подумал, что, возможно, включение вызовов Dojo provide
, require
и declare
в любой тип блока может вызвать проблему, поэтому я протестировал простое помещение рабочего кода в if (true) {
блок, и это все еще работает.
Последнее, что я пробовал на данный момент, — это добавить эту строку перед всем остальным, чтобы посмотреть, что define
такое:
console.log('dojo define',define);
… что нарушает его. В моем коде вообще нет сообщений консоли.
Затем я удаляю define
аргумент из этой новой строки, так что он просто отправляет строку на консоль, и код снова работает.
Похоже, что любое упоминание define
идентификатора автоматически останавливает выполнение остальной части кода.
В консоли нет ошибок или предупреждений, указывающих на проблему. Все, что я могу сказать на это, это: WTF?!
Теперь вместо этого вернемся к проверке dojo.version
.
Комментарии:
1. Просто предложение. Вы могли бы попробовать вложить код, специфичный для версии dojo, используя
dojo.version
смотрите здесь для деталей.2. @frank — Я знаю об
dojo.version
объекте, но я не вижу из этой документации, как я могу избежать дублирования всего тела моего класса, когда для разных версий Dojo нужно изменить только строкиdojo.provide
,dojo.require
иdojo.declare
.3. Известен другой модуль, который имеет
dojo.has
. смотрите здесь подробности, которые могут быть полезны для вашего сценария.dojo.has
может использоваться согласно этому руководству для создания конкретных сборок . Надеюсь, это поможет
Ответ №1:
Обычно оба должны по-прежнему работать, dojo.provide()
и dojo.require()
устарели, но не удалены полностью. Просто убедитесь, что ваш dojo загружается в синхронном режиме.
Кроме того, способ кодирования AMD представлен в Dojo 1.7, что означает, что он также должен поддерживаться в IBM Connections 4.5 (хотя я не знаю об IBM Connections 4).
Но если вы действительно хотите использовать обе базы кода, вы можете просто ссылаться на один и тот же объект вместо его дублирования, например:
var myModule = {
// Class fields and methods.
};
if (dojo.version.major == 1 amp;amp; dojo.version.minor == 9) {
define(['dojo/_base/declare','dojox.atom.io.model','dojox.atom.io.Connection'], function(declare){
return declare(null, myModule);
});
} else {
dojo.provide('insightCommunityWidgetClass');
dojo.require('dojox.atom.io.model');
dojo.require('dojox.atom.io.Connection');
dojo.declare('insightCommunityWidgetClass',null, myModule);
}
Или вы могли бы использовать следующую проверку:
if (typeof define === 'function' amp;amp; define.amd) {
// AMD style code
} else {
// Non-AMD style code
}
Это подход, используемый большинством библиотек с перекрестной загрузкой. Библиотеки, которые работают как на загрузчиках AMD (Dojo, Require.js ), но также на Node.js или просто с помощью глобального пространства имен используйте аналогичный фрагмент кода, чтобы определить, как они загружают свой модуль.
Комментарии:
1. Я действительно пытался сделать это таким образом. Похоже, у платформы widget есть проблема с этим. Ошибок нет, но метод onLoad виджета никогда не запускается, когда я пишу его таким образом. Я собираюсь попробовать определить класс как функцию с помощью прототипированных методов, как в пункте 1.2 phpied.com/3-ways-to-define-a-javascript-class .
2. Также отметим, что проверка на
define amp;amp; define.amd
кажется хорошим предложением; лучше, чем проверка номеров версий.3. @ScottLeis Действительно, я думаю, что это предпочтительный способ проверки этих вещей. Многие библиотеки делают это, например, взгляните на Moment.js в котором выполняется аналогичная проверка: github.com/moment/moment/blob/develop/moment.js#L2723
4. Я обновил свой вопрос подробностями странной проблемы, которую я пытался проверить
define
. Я снова попытался установить переменную класса (как в вашем ответе), и теперь это, похоже, работает в соединениях 4.0 и 4.5, поэтому, должно быть, я допустил какую-то ошибку, когда это решение изначально не удалось. В настоящее время возникают большие проблемы с нашей средой Connections 5.0 (Dojo 1.9), поэтому может пройти несколько дней, прежде чем я смогу подтвердить ответ.5. В вашем старом коде, который вы используете
dojo.require()
, в AMD есть разница междуrequire()
иdefine()
.define()
работает, только если модуль позже импортируется внутриrequire()
функции. Такdefine()
работает только для определения модулей, но для того, чтобы использовать этот модуль, вам нужноrequire()
это.
Ответ №2:
Это не ваш код, он должен работать как есть. Недавно мы столкнулись с той же проблемой и определили причину.
В Connections 5 используется AMD-версия Jazz framework, которая предоставляет собственный загрузчик dojo. Этот фреймворк используется для объединения необходимых модулей dojo в один JS-файл, что ограничивает количество запросов к серверу. К сожалению, этот загрузчик больше не обрабатывает синхронную загрузку модулей. Сбой с предупреждением, о котором вы сообщали, когда dojo.require() запрашивает модуль, который еще не загружен агрегатором. Если модуль уже был загружен, потому что он был частью агрегированного файла Jazz, тогда он работает. Это объясняет, почему вы можете dojo.require() использовать некоторые модули, но не все из них.
-> Обходной путь заключается в развертывании пакета OSGi на стороне сервера, чтобы получить нужные вам модули из агрегированного JS-файла. Для этого существует документированная точка расширения. Это может разблокировать вас и одновременно повысить производительность вашей страницы.
Теперь мы открыли PMR для службы поддержки IBM. Команда разработчиков работает над разрешением. Мы надеемся, что они смогут исправить ситуацию в ближайшее время.
Мы сообщили о следующих проблемах:
- dojo.require()
- dojo.требуется локализация()
- dojo.registerModulePath()/требовать({пути:})
Если вы подумаете о чем-то другом, пожалуйста, дайте мне знать.
Комментарии:
1. Спасибо, Филипп. Это очень интересно. Я буду следить за любыми исправлениями подключений, связанными с этим.
2. Как я понял, это должно быть исправлено в C5 CR1, а также с iFix, если вам это нужно раньше.