Как реактивность Метеор работает за кулисами?

Я прочитал docs и посмотрел на источник реактивность, но я этого не понимаю.

Может кто-нибудь объяснить, как это работает за кулисами, поскольку для меня это выглядит как волшебство:).

Ответ 1

Итак, это на самом деле довольно прямолинейно, на базовом уровне задействованы 2 типа функций:

  • Функции, которые создают реактивный контекст (реактивная функция)

  • Функции, которые недействительны для реактивного контекста (функция недействительности)

  • Функции, которые могут выполнять оба. (Я соврал там 3)

Когда вы вызываете reactive function, он создает context, который хранит метеориты по всему миру и к которому reactive function подписывается обратный вызов invalidation. Функция, которую вы передаете реактивной функции или любые функции, которые запускаются внутри нее, может быть invalidating function и может захватывать текущий context и сохранять ее локально. Эти функции могут тогда в любой момент, например, при обновлении db или просто вызове таймера, недействительны, что context. Первоначальный reactive function затем получит это событие и переоценит себя.

Здесь шаг за шагом, используя функции метеора (обратите внимание, что Tracker.autorun называлось Deps.autorun):

Tracker.autorun(function(){ 
  alert("Hello " + Session.get("name"));
});

Session.set("name", "Greg");
  • autorun принимает функцию в качестве параметра
  • до запуска этой функции автозапуск создает context
  • autorun присоединяет обратный вызов к событию недействительности context
  • Этот обратный вызов будет повторно запускать функцию, переданную автозагрузчику
  • Функция затем запускается в context в первый раз.
  • Meteor сохраняет этот context глобально как текущий активный context
  • Внутри функции есть еще одна функция: Session.get()
  • Session.get() является как reactive function, так и invalidating function
  • Session.get устанавливает свой собственный context и связывает его внутри с ключом "имя"
  • Session.get извлекает текущий контекст (контекст автозапуска) глобально из метеора
  • Обратный вызов недействительности, который Session.get регистрирует в своем собственном контексте, просто приведет к недействительности его включения контекста (в данном случае контекста автозапуска)
  • Итак, теперь у нас есть 2 контекста: autorun и session.get
  • когда эти функции возвращаются, метеорит очищает глобальную переменную активного контекста

  • Session.set - это еще одна функция, которая может привести к недействительности context.

  • в этом случае мы аннулируем все context, созданные сеансом, связанным с ключом "имя"
  • Все те contexts, когда они недействительны, запускают свои обратные вызовы недействительности.
  • Эти обратные вызовы просто недействительны для их включения context (что дизайн Session.get, а не то, что должен делать обратный вызов недействительности)
  • Те, кто заключает contexts, теперь выполняют свои обратные вызовы недействительности.
  • В случае автозапуска этот обратный вызов запускает функцию, которую мы первоначально передали автозапуску, а затем снова устанавливает context.

Вся реализация на самом деле довольно прямолинейна, вы можете увидеть ее здесь:
https://github.com/meteor/meteor/blob/master/packages/tracker/tracker.js

И хороший пример того, как это работает, можно найти здесь:
https://github.com/meteor/meteor/blob/master/packages/reactive-dict/reactive-dict.js

Реактивное программирование на самом деле не является метеорным или JS-специфическим
вы можете прочитать об этом здесь: http://en.wikipedia.org/wiki/Reactive_programming