Комментарии 14
Не надо бояться страшных зверей и новых технологий.
Полностью согласен. Если у всех россиян 100 мбит, LTE, intel core i5, айфон последней модели и закрыты все вкладки в браузере кроме сайта тинькофа.
(на моммент публикации размер главной страницы весит уже 2.5Мб вместо 3
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
в компонентах? В чем же выигрыш тогда?
Потребует улучшения архитектуры, да :-) Когда я интегрировал атомы с ангуляром получалось как-то так:
- Ангуляровская компонента — это инстанс какого-то класса.
- У инстанса есть реактивные свойства.
- Когда инстанс убивается ($onDestroy) — прибиваются все его реактивные свойства.
- Когда меняется какое-либо реактивное свойство — вызывается отложенный рендеринг (digest).
- Каждое реактивное свойство имеет формулу.
- Формула может обращаться к другим реактивным переменным, например, к модели, а та к хттп ресурсу.
- Реактивные переменные сами отслеживают от кого зависят и кто зависит от них.
- Как только зависимых не остаётся, реактивная переменная самоуничтожается.
- Реактивная переменная, привязанная к запросу, при уничтожении останавливает запрос.
А код компоненты может выглядеть как-то так:
class MyProfile extends MyComponent {
@frp get userName() {
return HTTP.get('/user/').name
}
}
DI добавьте по вкусу :-)
а $onDestroy
в данном подходе реализует кто? я так предполагаю, @frp
записывают себя в некий реестр в инстансе MyProfile
, с которым потом работает MyComponent#onDestroy()
?
основная мысль вроде ясна, и теперь с ней согласен: Зоны в данной задаче излишни — есть задача синхронизировать ЖЦ компонент и запросов, которые уже друг о друге знают, поэтому достаточно при уничтожении компоненты пометить выпущенные ею запросы как "неактуальные"; для этого у запросов должен быть соотв. интерфейс;
в вашем варианте это решается оборачиванием запросов (и аналогичных ресурсов) в реактивные переменные; и у автора, и у вас запросы учитываются на уровне методов компоненты с помощью декоратора метода (@cancellable
vs @frp
), только у автора все отслеживает зона, в вашем (по моему предположению) все отслеживает сам компонент как инстанс MyComponent
.
Верно понял вашу мысль?
На второй взгляд пример кажется не очень жизненным: если пользователь начинает какую-то операцию, он же должен узнать о ее результате, иначе он будет рассчитывать на успех; поэтому обычно уведомления об ошибках (а бывает, и об успехе) отображаются в некой области, не зависящей от текущего контекста; классический пример — ButterBar (желтая полоска вверху) в Gmail. Для такого отображения не нужно отслеживать ЖЦ компоненты, вызвавшей запрос. Компонента при этом может также обработать результаты и по-своему.
Четкий пацан Zone.js