Angular - AsyncPipe с оператором Observable map

Я пытаюсь реализовать небольшой инструмент перевода с Angular 5. Идея состоит в том, чтобы вызвать метод из шаблона, который будет переводить строку из динамически сгенерированного списка переводов.

В приведенном ниже коде строка не отображается, хотя вызывается оператор карты.

// NOT WORKING

@Component({
  selector: 'app-translate',
  template: '<h1>{{translate("Takeaway") | async}}</h1>'
})
export class TranslateComponent {
  private translateChange = new Subject<any>();
  private translateChange$;

  constructor() {
    this.translateChange$ = this.translateChange.asObservable();

    setTimeout(() => {
      this.translateChange.next({
        'Takeaway': 'To go'
      });
    }, 1000);
  }

  translate(str: string) {
    return this.translateChange$.map((nameList) => {
      return nameList.str || str;
    });
  }
}

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

// WORKING

@Component({
  selector: 'app-translate',
  template: '<h1>{{translate("Takeaway") | async}}</h1>'
})
export class TranslateComponent {
  private translateChange = new Subject<any>();
  private translateChange$;

  constructor() {
    this.translateChange$ = this.translateChange.asObservable();

    setTimeout(() => {
      this.translateChange.next('To go');
    }, 1000);
  }

  translate(str: string) {
    return this.translateChange$;
  }
}

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

Спасибо!

Это не сработает: nameList.str || str. Вы должны использовать nameList[str] || str, иначе он всегда пытается найти значение с ключом str, а не с ключом, который вы указали.

tom van green 08.05.2018 11:52

@tomvangreen Хорошее место! Но все же в этом случае он должен вернуть переданную строку из-за символа «|| str », что у меня на месте.

m.spyratos 08.05.2018 13:23
Тестирование функциональных 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
0
2
725
1

Ответы 1

Итак, я вижу несколько вещей, которые кажутся немного странными в вашем примере.

Повторно использовать существующие библиотеки

Я не понимаю, зачем вы здесь пытаетесь изобрести велосипед. Существует несколько библиотек перевода, которые уже можно использовать с angular. Я бы посоветовал взглянуть на ngx-translate и посмотреть, соответствует ли он вашим потребностям.

Но на случай, если вы все же захотите создать свой собственный, есть еще кое-что.

Предмет

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

Попробуйте вместо этого использовать BehaviorSubject. Субъект излучает только один раз, когда устанавливается новое значение. BehaviorSubject всегда будет выдавать последнее установленное значение, и вам необходимо указать начальное значение. Теперь предположим, что у вас есть блок в вашем шаблоне, который скрыт * ngIf. Через 1000 мс (что вы делаете в своем конструкторе) объект выдаст значение. Если вы показываете часть в блоке * ngIf после того, как это произошло, она никогда не получит значения.

С BehaviorSubject будет использоваться последнее переданное значение, поэтому в этом случае все будет в порядке.

Обеспечение функциональности с помощью метода в вашем компоненте

Я думаю, что предоставлять перевод каким-либо методом в вашем компоненте - не лучшая идея. Если вы хотите использовать перевод в любом другом компоненте, вам необходимо создать метод перевода. Я бы предпочел специальную трубку.

ngx-translate делает это примерно так:

{{ 'translationKey' | translate }}

И вы можете использовать его в каждом компоненте.

Я бы, вероятно, создал службу перевода, которая отвечает за отслеживание активных переводов (в основном, служба перевода содержит наблюдаемую translations$) и канал, который имеет службу в качестве зависимости и выполняет фактическое отображение из словаря перевода в переведенное значение . Если вы решили пойти по этому маршруту, убедитесь, что труба отмечена как нечистая.

Отлично, пока не изменилось

Я бы, наверное, добавил оператор distsinctUntilChanged() после вашего оператора карты. Вы хотите выдавать значения только в том случае, если они изменились. Вы можете изменить объект, содержащий ваши переводы, но некоторые значения останутся прежними. В этом случае вам не нужно снова излучать.

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