Движок правил wb-rules 1.7: различия между версиями

Материал из Wiren Board
Строка 1: Строка 1:
В обновлённом движке правил wb-rules присутствует ряд важных нововведений, касающихся логики написания сценариев.
В обновлённом движке правил wb-rules присутствует ряд важных нововведений, касающихся логики написания сценариев.


= Нововведения =
= Сценарии =


== Сценарии ==
== Изоляция сценариев ==
 
=== Изоляция сценариев ===


Начиная с версии wb-rules 1.7, каждый файл сценария запускается в своём отдельном пространстве имён - '''контексте'''. Таким образом, каждый сценарий может определять
Начиная с версии wb-rules 1.7, каждый файл сценария запускается в своём отдельном пространстве имён - '''контексте'''. Таким образом, каждый сценарий может определять
свои функции и глобальные переменные без риска изменить поведение других сценариев.
свои функции и глобальные переменные без риска изменить поведение других сценариев.


==== Пример ====
=== Пример ===
В качестве примера приведём два сценария, одновременно запускаемых в движке правил.
В качестве примера приведём два сценария, одновременно запускаемых в движке правил.
Каждый сценарий определяет глобальные переменные и функции.
Каждый сценарий определяет глобальные переменные и функции.
Строка 46: Строка 44:
</syntaxhighlight>
</syntaxhighlight>


==== Примечание ====
=== Примечание ===


В предыдущих версиях wb-rules для изоляции правил рекомендовалось использовать замыкание, т.е.  
В предыдущих версиях wb-rules для изоляции правил рекомендовалось использовать замыкание, т.е.  
Строка 59: Строка 57:
использующие эту конструкцию, продолжат работу без изменений в поведении.
использующие эту конструкцию, продолжат работу без изменений в поведении.


==== Обходной путь ====
=== Обходной путь ===


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


===== Использование модулей =====
==== Использование модулей ====


см. Модули
см. Модули


===== Прототип глобального объекта =====
==== Прототип глобального объекта ====


'''ВНИМАНИЕ:''' метод считается "грязным", т.к. все переменные и функции, опубликованные таким образом,
'''ВНИМАНИЕ:''' метод считается "грязным", т.к. все переменные и функции, опубликованные таким образом,
Строка 98: Строка 96:
Таким образом, первый способ обращения будет работать только в том случае, если myVar не определена в верхних областях видимости.
Таким образом, первый способ обращения будет работать только в том случае, если myVar не определена в верхних областях видимости.


=== Анонимные правила ===
== Анонимные правила ==


Теперь правила можно объявлять анонимно (без задания специального имени). Это позволит уменьшить путаницу и неочевидное
Теперь правила можно объявлять анонимно (без задания специального имени). Это позволит уменьшить путаницу и неочевидное
Строка 110: Строка 108:
именами в одном файле теперь будет возвращаться ошибка.
именами в одном файле теперь будет возвращаться ошибка.


==== Пример ====
=== Пример ===


<syntaxhighlight lang="js">
<syntaxhighlight lang="js">
Строка 121: Строка 119:
</syntaxhighlight>
</syntaxhighlight>


== Модули ==
= Модули =

Версия 14:43, 7 марта 2017

В обновлённом движке правил wb-rules присутствует ряд важных нововведений, касающихся логики написания сценариев.

Сценарии

Изоляция сценариев

Начиная с версии wb-rules 1.7, каждый файл сценария запускается в своём отдельном пространстве имён - контексте. Таким образом, каждый сценарий может определять свои функции и глобальные переменные без риска изменить поведение других сценариев.

Пример

В качестве примера приведём два сценария, одновременно запускаемых в движке правил. Каждый сценарий определяет глобальные переменные и функции.

В предыдущих версиях wb-rules обращение к глобальной переменной, изменяемой в нескольких файлах сценариев, может привести к неопределённому поведению. В версиях, начиная с 1.7, поведение строго определено и такое же, как будто сценарий единственный в системе.

В комментариях указан вывод команд log для ранних версий и для актуальной версии.

Сценарий 1 (rules1.js)

test1 = 42;

setTimeout(function myFuncOne() {
    log("myFuncOne called");
    log("test1: {}, test2: {}", test1, test2);
    // раньше: test1: [либо 42, либо 84], test2: Hello
    // теперь: test1: 42, test2: (undefined)
    // (будет выведена ошибка выполнения: ReferenceError: identifier 'test2' undefined)
}, 1000);

Сценарий 2 (rules2.js)

test1 = 84;
test2 = "Hello";

setTimeout(function myFuncTwo() {
    log("myFuncTwo called");
    log("test1: {}, test2: {}", test1, test2);
    // раньше: test1: [либо 42, либо 84], test2: Hello
    // теперь: test1: 84, test2: Hello
}, 1000);

Примечание

В предыдущих версиях wb-rules для изоляции правил рекомендовалось использовать замыкание, т.е. оборачивание кода сценария в конструкцию:

(function() {
    // код сценария идёт здесь
})();

Начиная с версии 1.7, в подобной конструкции нет необходимости. Тем не менее, старые сценарии, использующие эту конструкцию, продолжат работу без изменений в поведении.

Обходной путь

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

Использование модулей

см. Модули

Прототип глобального объекта

ВНИМАНИЕ: метод считается "грязным", т.к. все переменные и функции, опубликованные таким образом, становятся доступными всем сценариям в системе. Старайтесь избегать этого способа. За неопределённое поведение при использовании этого метода несёт ответственность сам программист.

Глобальные объекты всех сценариев имеют общий объект-прототип, в котором определены стандартные функции wb-rules (такие, как defineRule, setTimeout и т.д.). Через него можно передавать переменные или функции в общую область видимости.

global.__proto__.myVar = 42; // теперь myVar - общая переменная для всех сценариев

// из других сценариев к переменной можно обращаться так
log("shared myVar: {}", myVar);

// или вот так, что чуть более аккуратно, т.к. однозначно показывает, где определена переменная
log("shared myVar: {}", global.__proto__.myVar);

Правило поиска переменной в первом случае будет выглядеть так:

  1. Проверяем, есть ли myVar среди локальных переменных (определённой как var myVar = ...).
  2. Если нет, проверяем, есть ли myVar в глобальном объекте (определённой как myVar = ...).
  3. Если нет, проверяем, есть ли myVar в прототипе глобального объекта (определённой как global.__proto__.myVar).

Поиск останавливается, как только переменная найдена.

Таким образом, первый способ обращения будет работать только в том случае, если myVar не определена в верхних областях видимости.

Анонимные правила

Теперь правила можно объявлять анонимно (без задания специального имени). Это позволит уменьшить путаницу и неочевидное поведение системы при дублировании имён правил в одном скрипте.

Уникальные имена для анонимных правил генерируются автоматически.

Старый синтаксис (с явным заданием имени правила) продолжит работу без изменений.

ВНИМАНИЕ: начиная с версии 1.7, при объявлении правил с одинаковыми именами в одном файле теперь будет возвращаться ошибка.

Пример

defineRule({
    whenChanged: "mydev/test",
    then: function() {
        log("mydev/test changed");
    }
});

Модули