Утечка Angular Memory и подписка не работают должным образом - PullRequest
0 голосов
/ 07 мая 2018

Я даю попробовать Ionic, и я хотел на практике использовать конвертер валют. Приложение извлекает некоторые данные из API Rest, затем в интерфейсе используется для расчета курса определенной суммы денег. Я хочу, чтобы он работал так же, как и preev.com.

У меня есть служба, которая получает данные от API Rest и принимает два параметра, которые являются валютами для конвертации. Затем служба отправляет запрос на получение нужной конечной точки в зависимости от параметров / валют.

На моей странице есть функция, которая отправляет параметры / валюты в службу, а затем подписывается на нее.

В этой части я испытываю две проблемы:

  1. Первое, потому что это наблюдаемый, он обновляется слишком часто. Я пытался решить эту проблему, делая интервальный запрос к серверу каждые 60 секунд, но это не сработало, и другой путь, которым я пытался решить эту проблему, был попыткой получить значение один раз из компонента перед подпиской, используя метод first() .

  2. Когда я переключаюсь между валютами в моем выбранном компоненте, targetAmount мигает между текущим обменным значением и прошлым обменным значением. Например, валютами по умолчанию для обмена в моем приложении являются BTC / CLP, но когда я выбираю BTC / COP, он мигает два обменных курса в течение нескольких секунд, пока не покажет текущий обменный курс, который я и намерен сделать. Наконец, когда я переключаюсь между валютами, не дожидаясь показа только текущего обмена, происходит сбой.

Вот мой код:

Страница:

export class Page {

  baseCurrency = 'BTC';
  targetCurrency = 'CLP';
  baseAmount = 1;
  exchangeRate: number;
  subscription;

  constructor(public navCtrl: NavController,
    private exchangeService: ExchangeService) {

  }

  supportedCurrencies = ['BTC', 'ETH', 'BCH'];
  supportedCurrencies2 = ['CLP', 'COP', 'PEN'];

  get targetAmount() {
    this.subscription = this.exchangeService.getBudaFiat(this.baseCurrency, this.targetCurrency)
    .first()
    .subscribe(
      val => {
        this.exchangeRate = val.ticker.last_price[0];
      }
    )
    return this.baseAmount * this.exchangeRate;
  }

  ionViewWillLeave() {
    this.subscription.unsubscribe();
    console.log("SALIO");
  }

}

HTML:

<ion-content>
  <ion-list>
    <input type="number" [(ngModel)]="baseAmount"
      [class.error]="isInvalid(baseAmount)">
    <currency-select [(selected)]="baseCurrency"></currency-select>
    = <strong>{{targetAmount}}</strong>
    <currency-select2 [(selected)]="targetCurrency"></currency-select2>
    <p *ngIf="isInvalid(baseAmount)">Please enter a valid amount</p>
  </ion-list>
</ion-content>

Услуги:

getBudaFiat(baseCurrency: string, targetCurrency: string) {
    return Observable.interval(60000)
    .startWith(0)
    .switchMap(() => {
      return this.http.get(`https://wt-e2369b36b992e69ccc8f05d9b48dd8e2-0.sandbox.auth0-extend.com/cryptoalarma/${baseCurrency}${targetCurrency}`)
      .map((response: Response) => response);
    });
  }

Код также доступен на Stackblitz, и вы можете проверить проблему на вкладке Контакт:

Ссылка на приложение Stackblitz

Спасибо за вашу помощь!

EDIT:

Извините, я забыл упомянуть, что во второй проблеме, которую я объяснил, она начинает использовать много памяти, пока приложение не зависает.

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Я использую этот способ, который очень аккуратный, и вам не нужно создавать переменные для каждой подписки

  1. создать переменную с именем alive по умолчанию true
  2. Использовать .takeWhile(() => this.alive) до subscribe
  3. агрегат OnDestroy
  4. установить alive в false на ngOnDestroy

затем автоматически он отменит подписку наблюдаемой, когда ваш компонент уничтожен

export class MyComponent implements OnDestroy, OnInit {

  public user: User;
  private alive: boolean = true;

  public ngOnInit() {
    this.userService.authenticate(email, password)
      .takeWhile(() => this.alive)
      .subscribe(user => {
        this.user = user;
      });

    this.otherService.getdata()
      .takeWhile(() => this.alive)
      .subscribe(data => {
      });

  }

  public ngOnDestroy() {
    this.alive = false;
  }

}

Вы можете прочитать больше в здесь

0 голосов
/ 07 мая 2018

Вам необходимо правильно импортировать подписку:

import {Subscription} from 'rxjs/Subscription';

и введите переменную подписки:

subscription: Subscription;

и, наконец,

this.subscription.unsubscribe();
...