|
|
Строка 13: |
Строка 13: |
|
| |
|
| Предполагается, что при обновлении с предыдущей на следующую версию wb-rules и при соблюдении гайдлайнов при написании скриптов - все сценарии продолжат работать без каких-либо изменений. | | Предполагается, что при обновлении с предыдущей на следующую версию wb-rules и при соблюдении гайдлайнов при написании скриптов - все сценарии продолжат работать без каких-либо изменений. |
| Далее перечислены возможные проблемы в связи с изменением логики обработки скриптов новыми версиями движка.
| | Здесь перечислены возможные проблемы в связи с изменением логики обработки скриптов новыми версиями движка - [[Совместимость скриптов при обновлении wb-rules| Совместимость скриптов]]. |
| | |
| === Обновление до версии 2.2 ===
| |
| | |
| С версии 2.2 стали более строго проверяться типы устанавливаемых значений для контролов:
| |
| | |
| если для установления признака включено/выключено для контролов типа switch, клики по pushbutton или присваивание значений контролам с типом text применялась недокументировання возможность
| |
| использования для этой цели числовые значения (1, 0 и т.д.) в версии движка 2.2 операция присваивания не выполнится и завершится с ошибкой.
| |
| Корректный способ — устанавливать булевы значений (true/false) для switch/pushbutton и строковые значения для типа text
| |
| | |
| При возникновении подобной проблемы в логах можно видеть подобные записи:
| |
| <pre>
| |
| ERROR: control wb-mr3_30/K1 SetValue() error: can't convert control value '1' (type float64) to datatype 'switch'
| |
| ERROR: control system/Reboot SetValue() error: can't convert control value '1' (type float64) to datatype 'pushbutton'
| |
| ERROR: control status/someStatus SetValue() error: can't convert control value '-1.47' (type float64) to datatype 'text'
| |
| </pre>
| |
| | |
| Вместо:
| |
| <syntaxhighlight lang="ecmascript">
| |
| dev["wb-mr3_30"]["K1"] = 1 // включение
| |
| dev["status"]["someStatus"] = -1.47 // float
| |
| </syntaxhighlight>
| |
| | |
| Нужно:
| |
| <syntaxhighlight lang="ecmascript">
| |
| dev["wb-mr3_30"]["K1"] = true // включение
| |
| dev["status"]["someStatus"] = (-1.47).toString() // text
| |
| </syntaxhighlight>
| |
| | |
| === Обновление до версии 1.7 ===
| |
| | |
| Начиная с версии wb-rules 1.7, локальные переменные и функции, объявленные в файле сценария не видны в других сценариях.
| |
| Таким образом, каждый сценарий может определять свои функции и переменные без риска изменить поведение других сценариев.
| |
| | |
| В качестве примера приведём два сценария, одновременно запускаемых в движке правил. Каждый сценарий определяет переменные и функции.
| |
| В предыдущих версиях wb-rules обращение к переменной, изменяемой в нескольких файлах сценариев, может привести к неопределённому поведению.
| |
| В версиях, начиная с 1.7, поведение строго определено и такое же, как будто сценарий единственный в системе.
| |
| | |
| Сценарий 1 (rules1.js):
| |
| <syntaxhighlight lang="ecmascript">
| |
| var test1 = 42;
| |
| | |
| setInterval(function myFuncOne() {
| |
| log("myFuncOne called");
| |
| log("test1: {}", test1);
| |
| log("test2: {}", test2);
| |
| }, 5000);
| |
| </syntaxhighlight>
| |
| | |
| Сценарий 2 (rules2.js):
| |
| <syntaxhighlight lang="ecmascript">
| |
| var test1 = 84;
| |
| var test2 = "Hello";
| |
| | |
| setInterval(function myFuncTwo() {
| |
| log("myFuncTwo called");
| |
| log("test1: {}, test2: {}", test1, test2);
| |
| }, 5000);
| |
| </syntaxhighlight>
| |
| | |
| Было:
| |
| <pre>
| |
| 2019-01-05 17:29:50 myFuncTwo called
| |
| 2019-01-05 17:29:50 test1: 84, test2: Hello
| |
| 2019-01-05 17:29:50 myFuncOne called
| |
| 2019-01-05 17:29:50 test1: 84
| |
| 2019-01-05 17:29:50 test2: Hello
| |
| </pre>
| |
| | |
| Стало:
| |
| <pre>
| |
| 2019-01-05 17:28:42 myFuncTwo called
| |
| 2019-01-05 17:28:42 test1: 84, test2: Hello
| |
| 2019-01-05 17:28:42 myFuncOne called
| |
| 2019-01-05 17:28:42 test1: 42
| |
| 2019-01-05 17:28:42 ECMAScript error: ReferenceError: identifier 'test2' undefined
| |
| duk_js_var.c:1232
| |
| myFuncOne /etc/wb-rules/rules1.js:6 preventsyield
| |
| </pre>
| |
| | |
| Возможные способы решения проблемы:
| |
| | |
| '''Способ 1'''
| |
| | |
| Самый простой способ: перенести всю логику, которая использует доступ к переменной в другм файле в тот же файл, где определена переменная. Т.е. на примере приведённых выше правил нужно перенести всё в один файл rules1.js
| |
| <syntaxhighlight lang="ecmascript">
| |
| var test1 = 42;
| |
| var test2 = "Hello";
| |
| | |
| setInterval(function myFuncTwo() {
| |
| log("myFuncTwo called");
| |
| log("test1: {}, test2: {}", test1, test2);
| |
| }, 5000);
| |
| | |
| setInterval(function myFuncOne() {
| |
| log("myFuncOne called");
| |
| log("test1: {}", test1);
| |
| log("test2: {}", test2);
| |
| }, 5000);
| |
| </syntaxhighlight>
| |
| | |
| '''Способ 2'''
| |
| | |
| Следующий способ заключается в использовании глобального постоянного хранилища (PersistentStorage) ====
| |
| | |
| '''Внимание:''' при использовании глобальных постоянных хранилищ может произойти совпадение имён, в этом случае возможно труднообнаруживаемое нарушение поведения.
| |
| | |
| Вышеприведённый пример можно исправить следующим образом:
| |
| | |
| Сценарий 1 (rules1.js):
| |
| <syntaxhighlight lang="ecmascript">
| |
| var test1 = 42;
| |
| | |
| var ps = new PersistentStorage("my-global-storage", {global: true});
| |
| | |
| ps.test1 = test1;
| |
| | |
| setInterval(function myFuncOne() {
| |
| log("myFuncOne called");
| |
| log("test1: {}", test1);
| |
| log("test2: {}", ps.test2);
| |
| }, 5000);
| |
| </syntaxhighlight>
| |
| | |
| Сценарий 2 (rules2.js):
| |
| <syntaxhighlight lang="ecmascript">
| |
| var test2 = "Hello";
| |
| | |
| var ps = new PersistentStorage("my-global-storage", {global: true});
| |
| | |
| ps.test2 = test2;
| |
| | |
| setInterval(function myFuncTwo() {
| |
| log("myFuncTwo called");
| |
| log("test1: {}, test2: {}", ps.test1, test2);
| |
| }, 5000);
| |
| </syntaxhighlight>
| |
| | |
| | |
| '''Способ 3'''
| |
| | |
| "Грязный" способ, который использует прототип глобального объекта - использовать этот способ не рекомендуется из-за возможного замусоривания глобального пространства пользовательскими данными.
| |
| | |
| Исправленная версия:
| |
| | |
| Сценарий 1 (rules1.js):
| |
| <syntaxhighlight lang="ecmascript">
| |
| global.__proto__.test1 = 42;
| |
| | |
| setInterval(function myFuncOne() {
| |
| log("myFuncOne called");
| |
| log("test1: {}", global.__proto__.test1);
| |
| log("test2: {}", global.__proto__.test2);
| |
| }, 5000);
| |
| </syntaxhighlight>
| |
| | |
| Сценарий 2 (rules2.js):
| |
| <syntaxhighlight lang="ecmascript">
| |
| global.__proto__.test2 = "Hello";
| |
| | |
| setInterval(function myFuncTwo() {
| |
| log("myFuncTwo called");
| |
| log("test1: {}, test2: {}", global.__proto__.test1, global.__proto__.test2);
| |
| }, 5000);
| |
| </syntaxhighlight>
| |
|
| |
|
| == Как создавать и редактировать правила == <!--T:3--> | | == Как создавать и редактировать правила == <!--T:3--> |