Angular - 具有Observable map运算符的AsyncPipe

时间:2018-05-07 22:57:29

标签: angular rxjs angular5

我尝试使用Angular 5实现一个小型翻译工具。我们的想法是从模板中调用一个方法,该方法将从动态生成的翻译列表中翻译字符串。

在下面的代码中,虽然正在调用map运算符,但字符串未显示。

// 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;
    });
  }
}

有趣的是,如果我删除了map运算符并将字符串直接传递给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管道不匹配,以及是否有更好的方法来实现上述目标。

谢谢!

1 个答案:

答案 0 :(得分:0)

所以我在你的例子中看到了一些似乎有点不对劲的事情。

重用现有库

我不明白你为什么要在这里重新发明轮子。有多个转换库已经可以与angular一起使用。我建议您查看ngx-translate,看看它是否符合您的需求。

但是如果你还想建立自己的,还有其他一些东西。

<强>主题

我最好的猜测是,这是你的问题的原因。异步管道不纯,因此需要在每个变更检测周期重新评估。在您首次发出主题之前,它不会显示任何内容。在您发出一个值之后,只需一个额外的周期就可以再次停止订阅。

尝试使用BehaviorSubject。当设置新值时,主题将仅发出一次。 BehaviorSubject将始终发出已设置的最后一个值,您需要提供初始值。现在假设您的模板中有一个由* ngIf隐藏的块。在1000毫秒后(您在构造函数中执行的操作),主题将发出一个值。如果在发生这种情况后在* ngIf块中显示一个部分,它将永远不会收到值。

使用BehaviorSubject,将使用最后一个发射的值,因此在这种情况下你应该没问题。

通过组件中的方法提供功能

我认为通过组件中的方法提供翻译并不是一个好主意。如果要在任何其他组件中使用翻译,则需要创建翻译方法。我宁愿去自定义管道。

ngx-translate这样做很好:

{{ 'translationKey' | translate }}

您可以在每个组件中使用它。

我可能会创建一个翻译服务,它负责跟踪活动的翻译(基本上,翻译服务保存translations$可观察的)和一个将服务作为depdendency的管道,并进行实际的映射从翻译词典到翻译的价值。如果您决定走这条路线,请确保管道标记为不纯。

区别直到更改

我可能会在地图运算符后面添加一个distsinctUntilChanged()运算符。您只想在值发生变化时发出值。您可以更改包含翻译的对象,但保持一些值保持不变。对于这种情况,您不需要再次发射。