仅从 angular queryParams 获取最终值

get only final value from angular queryParams

我的目标是查明在加载应用程序时是否设置了查询参数 project。同时我还必须加载项目列表。当我得到这两个信息时,我可以继续我的逻辑。

这是我目前得到的结果

combineLatest([
  this.route.queryParams.pipe(pluck('project')),
  this.projects$.pipe(first(),filter(p => p && p.length > 0))
]).subscribe(([projectParam, projects]) => {
  console.log(projectParam, projects);
});

this.route是 ActivatedRoute 类型:https://angular.io/api/router/ActivatedRoute

projects$ observable 工作得很好。但是 queryParams observable 被调用了两次。一次使用值 undefined ,然后使用实际值。但我只想要最后一个值。 由于 url 是可选的,因此两个选项均有效。

知道如何让 queryParams 只触发最终值。

尝试使用最后一个 rxjs 运算符

this.route.queryParams.pipe(last(), pluck('project'))

this.route.queryParams 在内部实现为一个永远不会完成的主题,但您希望它在第一个不同于 undefined.

的值之后立即完成

所以你可以使用例如 takeWhile 和可选的第二个参数:

this.route.queryParams.pipe(
  takeWhile(val => val === undefined, true), // or maybe !Boolean(val)
  takeLast(1),
  pluck('project')),
)

或者只使用 filter()take(1).

可能会更容易

您可以使用跳过运算符跳过第一个。

 combineLatest([
      this.route.queryParams.pipe(pluck('project')),
      this.projects$.pipe(first(),filter(p => p && p.length > 0))
    ]).pipe(skip(1)).subscribe(([projectParam, projects]) => {
      console.log(projectParam, projects);
    });

为什么你不能简单地订阅 route.queryParams 并检查它是否有 project 参数。

这是我完成任务的想法。

ngOnInit() {
    this.route.queryParams.subscribe(queryParams => {
        if (queryParams.project) {
            // proceed with your logic
        }
    });
}

感谢这里的讨论:https://github.com/angular/angular/issues/12157 我提出了以下解决方案:

private get finalQueryParams$(): Observable<Params> {
  return merge(
    // get urls with query params like /test?project=test
    this.route.queryParams.pipe(
      filter(params => Object.keys(params).length > 0)
    ),
    // get urls without query params like /test
    this.route.queryParams.pipe(
      filter(() => !(window.location.href || '').includes('?')),
      map(() => ({}))
    )
  );
}

它只触发一次,我得到了 queryParams 的实际值。

在上面的代码中,我只需要将其更改为

combineLatest([
  this.finalQueryParams$.pipe(pluck('project')),
  this.projects$.pipe(first(),filter(p => p && p.length > 0))
]).subscribe(([projectParam, projects]) => {
  console.log(projectParam, projects);
});