powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / HTML, JavaScript, VBScript, CSS [игнор отключен] [закрыт для гостей] / Observable.subscribe вызывает повторный вызов.
14 сообщений из 14, страница 1 из 1
Observable.subscribe вызывает повторный вызов.
    #39404345
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проектик на Angular 2.

Вопрос1. Есть такой код:

Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public GetData (myparams: URLSearchParams):Observable<Response>{
	var observable = this.http.get(this.myUrl, { search: myparams });
	this.subscribeTo(observable);
	return observable;            
}

private SubscribeTo (request: Observable<Response>): void
{
	this.animationService.start();
	request.subscribe(  ()=>this.animationService.stop());
}



По какой-то причине, такой код приводит к двойному вызову бэкэнд-сервиса.

Но если я коменчу одну строку

Код: javascript
1.
2.
3.
4.
5.
public GetData (myparams: URLSearchParams):Observable<Response>{
	var observable = this.http.get(this.myUrl, { search: myparams });
//	this.subscribeTo(observable);
	return observable;            
}



То запрос уходит только один, как и должно быть. Почему ?
Я считал, что подписавшись на Observable мы лишь цепляем еще один обработчик события. После того, как http.get вернет данные, должны просто вызватся два обработчика. Мой, где я останавливаю анимацию, и любой другой, который подписался на событие.

В чем я ошибся ?

Вопрос2. Как правильней ?

Код: javascript
1.
2.
3.
4.
5.
6.
private SubscribeTo (request: Observable<Response>): void
{      
        var t = this;
	t.animationService.start();
	request.subscribe(  ()=>t.animationService.stop());
}


или
Код: javascript
1.
2.
3.
4.
5.
private SubscribeTo (request: Observable<Response>): void
{
	this.animationService.start();
	request.subscribe(  ()=>this.animationService.stop());
}
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39404388
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как я понимаю request.subscribe приводит к вызову request. Но почему ? Ведь мы просто цепляем обработчик события.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39404625
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Разобрался.
request.subscribe оказывается заставляет Observable стартовать.

Проверил под отладкой, зайдя в исходники.
https://github.com/ReactiveX/rxjs/blob/master/src/Observable.ts


Код: javascript
1.
2.
3.
4.
5.
if (operator) {
      operator.call(sink, this.source);
    } else {
      sink.add(this._trySubscribe(sink));   << Заходило сюда
    }



а затем, когда процедура возвращала Observable, то я применял к ней .toPromise(), а это тоже стартовала задачу.

Но странно даже не то, что подписчики форсируют старт задача. А то, что задача стартуется дважды, как 2 отдельные задачи, т.е. дважды создают побочный эффект. Вот это странно.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405331
Агнец за бортом
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsHeloWorlderНо странно даже не то, что подписчики форсируют старт задача.

Почитайте документацию. Ради прикола.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405343
Агнец за бортом
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsHeloWorlder Мой, где я останавливаю анимацию, и любой другой, который подписался на событие.

Начинай думать по другому. Ты строишь потоки данных и "слушаешь" их. А не "подписываешься" на события.

С простым Observable - каждый поток "свой и единственный" для каждого подписчика. С самого начала.

Я не знаю - как именно ты засетапил свою анимацию, но вызвать её через start()/stop() имхо неправильно.

Делай через классы css и bind на свойства TS-класса. А вот этими свойствами ты вполне можешь управлять из кода.

А если еще вспомнить о pipe async, то становится ясно что сделать bind ты можешь прямо к observable.

Также почитай про cold/hot observable / subject (и его 4-х разновидностях). А также о кешировании результата Observable (publishReplay().refCount())

У меня НЕ получилось написать ВСЮ логику программы на rxJS. Но очень хотелось. Ну, A2 к этому если и склоняет, то мягко; предоставляя выбор.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405572
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мое удивление от того, что подписывание на поток стартует задачу связанно с тем, что привык к тому, что в C# Task'и дефакто принято создавать уже "горячими" - т.е. запущеными. Остается только прицепить обработчики, ожидающие результата.
Это мне кажется логичным. А то, что какой-то подписчик на событие стартует задачу - это мне кажется не логичным. Потому, что этих подписчиков может быть миллион, и если каждый может стартовать задачу, то получаем не определенность. Не говоря уж о повторных стартах.
Ну наверное я пока еще чего-то не понимаю. Буду дальше изучать конечно.
Почитаю, что тут означают холодные и горячие observable. Разберусь хоть что refcount за зверь такой вообще. Есть еще с чем разбиратся, и мне это интересно :) Просто нужно разобраться.

Агнец за бортом
Делай через классы css и bind на свойства TS-класса.

Ну без css, но так я и делаю вроде

Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
export class AnimationService {
  public status: Subject<boolean> = new Subject();
  private _active: number = 0;

  public get active(): boolean {
    return (this._active>0);
  }

  public set active(v: boolean) {
    if (v==true)
        this._active ++;
    else
        this._active --;

    this.status.next(this._active>0);
  }

  public start(): void {
    this.active = true;
  }

  public stop(): void {
    this.active = false;
  }



активируется как уже показывал

Код: javascript
1.
2.
3.
4.
5.
public GetData (myparams: URLSearchParams):Observable<Response>{
	var observable = this.http.get(this.myUrl, { search: myparams });
	this.subscribeTo(observable);
	return observable;            
}



а на странице выводится так

Код: html
1.
2.
<animation-component></animation-component>
<router-outlet></router-outlet>



Не очень понимаю каким тут боком можно CSS прикрутить. И чем поможет pipe async (потому, что еще не разбирался с тем, что он делает).

В целом то работает уже. Я просто переписал, чтобы .toPromise вызывался внутри сервиса сразу, и работаю уже только с ним. Заодно, тем самым, форсю скорейший старт запроса.
К этому промису и цепляется анимация, а также вызывающий код. Observable вообще никуда не отдается и глубоко запрятан. Таким образом задача стартует только раз.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405593
Агнец за бортом
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsHeloWorlder Я просто переписал, чтобы .toPromise вызывался

Да нафига эти полумеры - оставался бы в рамках одной библиотеки.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405616
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Агнец за бортом,

Думал об этом )) Но по не опытности не знаю, как от Observable получить только один результат. Т.е. я шлю Get запрос и хочу получить один результат. С Promise все понятно. А с подпиской на поток не ясно - в какой там момент память освободится и не будет ли подписка висеть вечно. А при последующих запросах Get не будет ли утечек памяти (т.к. старые подписки еще остались). Просто пока слишком мало опыта.
Хорошо разбираюсь в Task'а в C# поэтому стараюсь найти какие-то параллели. Реактивное программирование, в общих чертах, понимаю. Нужно только разобраться с тонкостями, чтобы не плодить утечки памяти и проче. Думаю со временем разберусь.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405623
Агнец за бортом
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsHeloWorlderАгнец за бортом,

Думал об этом )) Но по не опытности не знаю, как от Observable получить только один результат. Т.е. я шлю Get запрос и хочу получить один результат. С Promise все понятно. А с подпиской на поток не ясно - в какой там момент память освободится и не будет ли подписка висеть вечно. А при последующих запросах Get не будет ли утечек памяти (т.к. старые подписки еще остались). Просто пока слишком мало опыта.
Хорошо разбираюсь в Task'а в C# поэтому стараюсь найти какие-то параллели. Реактивное программирование, в общих чертах, понимаю. Нужно только разобраться с тонкостями, чтобы не плодить утечки памяти и проче. Думаю со временем разберусь.


TsHeloWorlderНо по не опытности не знаю, как от Observable получить только один результат.

.take(1)

Но на самом деле, тебе это не нужно, так как тебя интересует _последний результат_. А bind к Observable делается так:

Код: javascript
1.
{{(user || async}})?.name



TsHeloWorlderА с подпиской на поток не ясно - в какой там момент память освободится и не будет ли подписка висеть вечно.

Можно отписаться. Но ты сам ими рулишь. Что значит "старые подписки еще остались", они тебе или нужны или не нужны.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405636
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Агнец за бортомЧто значит "старые подписки еще остались", они тебе или нужны или не нужны.


Меня смущает такой код в примерах:

Код: javascript
1.
2.
3.
return this.http.get(this.commentsUrl)
                        // ...and calling .json() on the response to return data
                         .map((res:Response) => res.json())



Реактивное программирование я понимаю так:
создаем Observable, вешаем прослушивателя на него (в данном примере Map). Который будет слушать до тех пор пока Observable не будет dispose или complete. Может в чем-то ошибаюсь, т.к. только начинаю разбираться.

http.get создает Observable<Response> на который подписывается .map. И потом эта связка висит вечно же ? Нигде не вижу ни dispose, ни complete.
А когда мы снова вызываем http.get, то он возвращает новый Observable<Response> - на который вешается еще один Map. А потом еще и еще. Сотни вызовов за время жизни программы. И все они попрождают Observable который слушает Map.

Опасаюсь утечки памяти. Почему ее не происходит ?

И вообще не понимаю, почему http.get возвращает Observable, если он, в принципе, вернет только один результат ? Почему не Promise ?
Это примерно как писать функцию, которая возвращает string[], но при этом мы четко знаем (и в спецификации это явно указано), что нужно из этого массива взять строго первый элемент и с ним работать. Со стороны такая спецификация выглядит глупостью. Или я чего-то пока не понял )
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405654
Агнец за бортом
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsHeloWorlderсоздаем Observable, вешаем прослушивателя на него (в данном примере Map).

Уже ошибка. .map - это не прослушиватель.

Короче, ты же с LINQ знаком?

Отложенное выполнение - в курсе что это?

Ну вот подписка и есть - начало итерирования/выполнения коллекции/observable

а pipe async кстати и подписывается на observable

TsHeloWorlder И потом эта связка висит вечно же ?

равно как и

Код: c#
1.
db.users.Select(x=>x.id)
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405672
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Агнец за бортом,

Код: c#
1.
db.users.Select(x=>x.id)


По моему это, как раз таки, разные вещи. Данный код материализует (тригерит отложенное выполнение, или возвращает закэшированный результат) конечный список List<User> и преобразовывает его в List<int>. Такой код категорически не сработает с бесконечным списком (когда можем бесконечно генерить через yield return). Observable же потенциально бесконечен. Пока он не завершится через complete или сами не отпишемся от него. Такой функционал в него заложен, он для того и создан. Почему http.get возвращает Observable, если результат может быть только один ?
Могу только предположить, что этот подход более в "функциональном стиле", только ради этого сделано.

В примерах я не видел, чтобы отписывались от результата вернутого из http.get. Обычно приводится к Promise, чтобы получить строго один ответ, после чего Observable, все же, самоуничтожается освобождая память. Я очень надеюсь, т.к. не исследовал по исходникам под отладчикам. Ну или иначе должны быть утечки в учебных примерах.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405727
Агнец за бортом
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TsHeloWorlderАгнец за бортом,

Код: c#
1.
db.users.Select(x=>x.id)


Данный код материализует (тригерит отложенное выполнение, или возвращает закэшированный результат) конечный список List<User> и преобразовывает его в List<int>.

Ничего он не материализует. Какой нафиг List?


TsHeloWorlderПочему http.get возвращает Observable, если результат может быть только один ?
Могу только предположить, что этот подход более в "функциональном стиле", только ради этого сделано.

Ну, это логично, ИМХО. Единообразие обработки и всё такое. RX предполагает потоки данных организованные много более сложнее чем http-запрос и обработка результата. И http-запрос - просто звено цепи.
...
Рейтинг: 0 / 0
Observable.subscribe вызывает повторный вызов.
    #39405756
TsHeloWorlder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Агнец за бортом,

А ну да. Не материализует IEnumerable, пока не будет вызван ToList, это я поспешил. Но я там имел ввиду именно разности этих вещей. В одном случае IEnumerable, который обычно конечен. В другом потенциально бесконечный поток событий, как например MouseClick.

Возвращаясь к Observable я так и не понял будут ли там утечки памяти и почему, если сценарий таков:

(опуская промежуточные слои, типа сервисов)
1. На вьюхе кликаем кнопку
2. Посылаем запрос через http.get
3. получаем Observable и преобразуем через toPromise
4. Возвращаем в компонент, который отвечает за вышеописанную вьюху
5. компонент считывает одно значение из Promise и подставляет в переменную, которая отрендерится на вьюхе.

B нигде, вроде, не делаем ни dispose ни complete.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / HTML, JavaScript, VBScript, CSS [игнор отключен] [закрыт для гостей] / Observable.subscribe вызывает повторный вызов.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]