Как стать автором
Обновить

Комментарии 14

Не надо бояться страшных зверей и новых технологий.

Полностью согласен. Если у всех россиян 100 мбит, LTE, intel core i5, айфон последней модели и закрыты все вкладки в браузере кроме сайта тинькофа.
(на моммент публикации размер главной страницы весит уже 2.5Мб вместо 3
Идея хорошая, но есть пара комментариев. Во-первых, а нужен ли вам для вашего кейса весь Zone.js? Из всего функционала вы использовали только одну функцию, которую можно было бы реализовать самому в ~10 строчек:

window.zone = {
    context: {},
    run: function(callback) {
        var backup = zone.context;
        zone.context = {};
        callback();
        zone.context = backup;
    }
}

Во-вторых, в примерах попадаются какие-то мелкие досадные вещи, которые должны вызывать вопросы на code review:

  • Ссылка на injector получается в обход DI
  • Из ZoneService возвращается нетипизированный объект, хотя zone.d.ts существует
  • «Пул запросов» — это не pull, а pool
спасибо, поправил
Ссылка на injector получается в обход DI

Да, на это пошли в виду внесения минимальных изменений. Решение с DI требует рефакторить сотни компонентов пробрасывая инжектор в родителя.
Из ZoneService возвращается нетипизированный объект, хотя zone.d.ts существует

Спасибо, упустили.
  • ссылку на injector можно передавать с помощью условного BaseController.setCurrentInjector() при старте приложения — это позволит и уйти от предположения, что body — корневой элемент приложения, и в принципе уберет ненужную ответственность из BaseController


  • текущая реализация довольно хрупка — разработчики должны помнить, что нужно вызывать super.constructor() (а, при написании своего $onDestroy, и super.$onDestroy()), причем такие ошибки, особенно с $onDestroy, могут заметить очень нескоро, и, скорее всего, уже пользователи;


    корень проблемы — в использовании наследования — class AccountsController extends BaseController:


    решение: превратить BaseController в декоратор класса, оборачивающий/создающий методы $onInit и $onDestroy


чОткий пацан

Zone.js все еще сыроват, применять надо аккуратно. Мне не удалось его подружить c XMLHttpRequest (валится с ошибкой при попытке переиспользовать объект запроса), в то время как в ангуляре2 все работает.

Вы вполне могли бы использовать реактивные переменные ($jin.atom, cellx, ko), которые умеют деактивироваться при потере подписчиков и не костылять на ZoneJS.

Как конкретно их использовать — оборачивать в них запросы к API? Разве не потребует это множества изменений кода приложения?


И разве для этого не надо будет от них отписываться явно, для чего нужно будет написать кучу $onDestroy в компонентах? В чем же выигрыш тогда?

Потребует улучшения архитектуры, да :-) Когда я интегрировал атомы с ангуляром получалось как-то так:


  1. Ангуляровская компонента — это инстанс какого-то класса.
  2. У инстанса есть реактивные свойства.
  3. Когда инстанс убивается ($onDestroy) — прибиваются все его реактивные свойства.
  4. Когда меняется какое-либо реактивное свойство — вызывается отложенный рендеринг (digest).
  5. Каждое реактивное свойство имеет формулу.
  6. Формула может обращаться к другим реактивным переменным, например, к модели, а та к хттп ресурсу.
  7. Реактивные переменные сами отслеживают от кого зависят и кто зависит от них.
  8. Как только зависимых не остаётся, реактивная переменная самоуничтожается.
  9. Реактивная переменная, привязанная к запросу, при уничтожении останавливает запрос.

А код компоненты может выглядеть как-то так:


class MyProfile extends MyComponent {
    @frp get userName() {
        return HTTP.get('/user/').name
    }
}

DI добавьте по вкусу :-)

а $onDestroy в данном подходе реализует кто? я так предполагаю, @frp записывают себя в некий реестр в инстансе MyProfile, с которым потом работает MyComponent#onDestroy()?


основная мысль вроде ясна, и теперь с ней согласен: Зоны в данной задаче излишни — есть задача синхронизировать ЖЦ компонент и запросов, которые уже друг о друге знают, поэтому достаточно при уничтожении компоненты пометить выпущенные ею запросы как "неактуальные"; для этого у запросов должен быть соотв. интерфейс;


в вашем варианте это решается оборачиванием запросов (и аналогичных ресурсов) в реактивные переменные; и у автора, и у вас запросы учитываются на уровне методов компоненты с помощью декоратора метода (@cancellable vs @frp), только у автора все отслеживает зона, в вашем (по моему предположению) все отслеживает сам компонент как инстанс MyComponent.


Верно понял вашу мысль?

Да, только компонента контролирует ЖЦ не всего и вся, а только своих собственных реактивных свойств, а от чего они там зависят — её не касается.

Разумеется) Спасибо!

На второй взгляд пример кажется не очень жизненным: если пользователь начинает какую-то операцию, он же должен узнать о ее результате, иначе он будет рассчитывать на успех; поэтому обычно уведомления об ошибках (а бывает, и об успехе) отображаются в некой области, не зависящей от текущего контекста; классический пример — ButterBar (желтая полоска вверху) в Gmail. Для такого отображения не нужно отслеживать ЖЦ компоненты, вызвавшей запрос. Компонента при этом может также обработать результаты и по-своему.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий