Как запустить одноразовый метод внутри хука жизненного цикла ngAfterViewChecked в Angular

У меня есть изменение переменной, которое нужно отслеживать, и я хочу запустить какую-то функцию после такого изменения. Итак, я использую хук ngAfterViewChecked для запуска функции. Однако этот метод представляет собой представление данных. Итак, его нужно запустить только один раз. Итак, я использовал логическую переменную состояния, чтобы обработать это следующим образом.

    ngAfterViewChecked() 
    {
        //status is a boolean variable which is true
        if (this.status)
        {
           this.status=!this.status;
           this.myFunction();
        }
    }
    myFunction
    {
        //some code
    }

Но я обнаруживаю несколько отправок данных в этом подходе (проверено после проверки базы данных), и я также получаю следующую ошибку.

ОШИБКА Ошибка: ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после проверки. Предыдущее значение для '@dialogContainer': 'enter'. Текущее значение: «выход».

Насколько я знаю, ngAfterViewChecked запускается для каждого изменения. Поэтому я предполагаю, что до изменения статуса на false выполнялся другой экземпляр if (this.status){} до того, как он был изменен на false.

Есть ли способ решить эту проблему?

ngAfterViewChecked — плохой хук для решения проблемы в 999 случаях из 1000. Что за сценарий this.status обновлен?

Andrei 11.12.2020 12:00

@ Андрей Вы предлагаете мне послушать изменение значения this.status? Я не получил ваш комментарий

sadisha nadiej 11.12.2020 14:08

Я еще ничего не предлагал. чтобы предоставить вам лучший вариант, мне нужно знать сценарий, как меняется this.status

Andrei 11.12.2020 14:14

@Andrei Андрей, я делал это внутри предложения if, чтобы убедиться, что оно больше не запустится. если (this.status) { this.status=!this.status; эта.моя функция(); }

sadisha nadiej 11.12.2020 14:16

@ Андрей Что-то не так с моим предложенным ответом?

sadisha nadiej 11.12.2020 14:18

Я бы сказал, что ваш ответ решает небольшую архитектурную ошибку, которая появилась раньше. Лучший способ - вызвать вашу логику, когда событие (которое в вашем случае обновляет "this.status") испускается. отслеживание переменных так, как вы пытаетесь, считается плохой практикой. Это одна из причин, по которой AngularJS мертв, а вместо него создается Angular2+.

Andrei 11.12.2020 14:22

@Andrei Так что я должен вызвать myFunction(), когда this.status выдается следующим образом. ngAfterViewChecked() { if (this.counter == 0) { this.counter++; если (this.counter == 1) { this.paymentListener.next(this.counter); эта.моя функция(); } } } Это правильно?

sadisha nadiej 11.12.2020 14:27

как я уже сказал, правильный способ - не использовать ngAfterViewChecked крючок. его называют слишком часто. Недостаточно контекста, чтобы помочь вам с точным вариантом, который вам нужен

Andrei 11.12.2020 14:29
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
8
489
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После нескольких часов поиска я смог это преодолеть. Вот как я это сделал. Я начну с небольшого объяснения моего решения.

  • Angular работает в браузере. Браузеры запускают JavaScript. Код Javascript выполняется в одном потоке, но среда выполнения Javascript не запускается в одном потоке. Нам не нужно об этом беспокоиться, так как Runtime позаботится об этом.
  • Субъект является наблюдаемым. Его можно использовать для передачи значения любому количеству наблюдателей, которые его слушают.
  • Подписка может содержать наблюдаемую

Сначала я создал тему с именем paymentListener, целочисленную переменную с именем counter и подписку с именем oneTimePayment.

oneTimePayment: Subscription;
  private paymentListener = new Subject<number>();
  counter = 0;

Затем внутри метода onInit я сделал подписку.

 ngOnInit() {
    
    this.oneTimePayment = this.paymentListener.subscribe((counter) => {
          if (counter == 1) {
            //this is my function
            this.myFunction();
          }
        });
    
    }

Затем внутри хука жизненного цикла ngAfterViewChecked я использовал paymentListener (это Subject) для выдачи значения счетчика.

 ngAfterViewChecked() {
    if (this.counter == 0) {
      this.counter++;
      if (this.counter == 1) {
        this.paymentListener.next(this.counter);
      }
    }
  }

Поскольку значение выдается обработчиком платежа (Subject) только в том случае, если счетчик равен 1. Таким образом, при подписке, сделанной внутри onInt, будет получено выданное значение, и там я выполняю myFunction() только в том случае, если выданное значение равно 1; Это гарантирует, что метод запускается только один раз после изменения.

Наконец, обязательно вызовите отмену подписки внутри ngOnDestroy. В противном случае это приведет к утечке памяти.

 ngOnDestroy() {
    this.oneTimePayment.unsubscribe();
  }

Другие вопросы по теме