Comments 10
Меня очень заинтересовал ваш проект и я решил повторить его на чём-то менее попсовом, например на $mol, сохранив основную функциональность - утечки.
Итак, вот сервис:
export class $my_leak_service extends $mol_object {
@ $mol_mem
static data( next = 0 ) {
return next
}
}
Вот, использующий его компонент:
$my_leak_carrier $mol_chip
title \Data carrier (data length: {size})
export class $my_leak_carrier extends $.$my_leak_carrier {
@ $mol_mem
data_from_service() {
return this.$.$my_leak_service.data()
}
@ $mol_mem
data() {
return this.$.$mol_fetch.json( 'https://mol.hyoo.ru/web.deps.json' ) as any
}
@ $mol_mem
size() {
return this.data().files.length
}
@ $mol_mem
title() {
return super.title().replaceAll( '{size}', this.size().toString() )
}
}
Ну и обвязка-переключатель:
$my_leak $mol_expander
title \Toggle data carrier
content / <= Carrier $my_leak_carrier
А теперь смертельный номер - запускаем профилирование памяти:

Ага, мы загрузили полтора метра данных, но где же наш сервис? А, точно, мы же к нему даже не обратились - вот он и не поднялся. Исправляемся:
export class $my_leak_carrier extends $.$my_leak_carrier {
// ...
@ $mol_mem
size() {
return this.data().files.length + this.data_from_service()
}
// ...
}
Ладно, сервис подняли, но вот чёрт, при закрытии компонента память зачем-то освобождается:

Ладно, план Б, переносим загрузку и хранение данных в сам сервис, в статический, чтоб его, синглтон:
export class $my_leak_service extends $mol_object {
@ $mol_mem
static data() {
return this.$.$mol_fetch.json( 'https://mol.hyoo.ru/web.deps.json' ) as any
}
}
export class $my_leak_carrier extends $.$my_leak_carrier {
@ $mol_mem
data() {
return this.$.$my_leak_service.data()
}
@ $mol_mem
size() {
return this.data().files.length
}
@ $mol_mem
title() {
return super.title().replaceAll( '{size}', this.size().toString() )
}
}
Ну теперь-то точно всё утечёт:

Да что ж это за напасть-то такая? Казалось бы, стандартная для enterprize фича, а на $mol её не реализовать. Жаль, а такой перспективный, казалось, фреймворк...
Сейчас ещё и минусов отхвачу за то, что не осилил...
А к чему вы устроили это цирковое представление? В вашем примере вы просто ссылаетесь на асинхронный метод $mol_fetch.json()
, это далеко не то же самое, как работают Observables в библиотеке rxjs. Если это какая-то насмешка над Ангуляром, то смею вас заверить, что его компоненты тоже никакого понятия о rxjs не имеют и никакого встроенного механизма автоматических отписок (которые могут быть еще и не желательны в отдельных случаях) не имеют. Не нравится rxjs - никто не запрещает использовать любую другую библиотеку или дефолтный fetch. А логика вида "подписался на что-то -- отпишись" справедлива для всего, при работе с асинхронным кодом.
Метод $mol_fetch.json()
, разумеется никакой не асинхронный. Да и никаких ручных подписок/отписок, как видите, в коде нет. Волшебство, не иначе.
К тому, что вся статья это цирк. Давайте рассудим логично:
1) описана реактиваная парадигма js.
2) главный принцип реактивного програамирования: а) подписка б) наблюдение в) отписка. И никак иначе.
3) статья основана на нарушении основных правил парадигмы.
Весь остальной бред высосан из пальца безмозглых программистов, которые нарушают самые фундоментальные правила, а потом удивляются - а "херли не работает?', "а кто это сделал?", "а куда утекает память?"
Тьфу....
Так я может не хочу отписываться каждый раз при destroy моего компонент, может мне нужно подписаться в какой-то момент и больше не отписываться. Если я пишу приложение на условном Angular - то это как правило SPA, оно может жить месяцами в открытом окне/табе без обновления страницы. И все это время подписка может жить, и это expected behaviour
Читаю про ангуляр только ради дополнительной статьи про $mol в комментариях
Спасибо за материал.
Без воды, буду подаванам скидывать почитать, почему важно помнить про отписку.
Как утекает память, если забыть отписаться от Observable