【问题标题】:pluck + map rxjs with Angular 8 not working?pluck + map rxjs 与 Angular 8 不工作?
【发布时间】:2020-11-05 00:59:11
【问题描述】:

所以我有一个来自 api 的返回对象,其结构如下:

{
  status: 'ok',
  stuff: [array of objs],
  page: xyz
}

我正在使用“pluck”运算符来提取属性“stuff”。但是,我需要在它上面运行一个 map 运算符,并为返回的 stuff 对象数组中的每个对象添加一个新属性。到目前为止,我的 map 运算符正在将属性添加到数组的末尾(而不是添加到每个对象)。想知道我哪里错了。

this.blogsFromAPI$ = 
    this.blogService
        .getBlogs()
        .pipe(
          pluck('stuff'),
          map(st => {
            st.url = "myurl" + st.alias;
            console.log(st );
          })
        );
  }

然后,我想按日期时间按最近的顺序对数组进行排序。像这样的:

// this.blogsFromAPI$ = this.blogService.getBlogs().pipe(
    //   pluck('articles'),
    //   map(articles => articles.map(a => {
    //     // take articles array from return object, loop over them, 
    //     // construct redirect url & return a new obj with the new property
    //     a.url = "http://globalfinancialdata.com/" + a.alias;
    //     return a;
    //   }), map(art => art.sort((a, b) => new Date(b.published_at).getTime() - new Date(a.published_at).getTime())))
    // );

【问题讨论】:

  • stuff 是一个数组,你可能需要遍历每个元素才能得到你想要的结果
  • 但 map 无法在“stuff”中的每个元素上运行代码并进行这些更改。是为了数据转换,对吧?
  • 附带说明,改变值是一种副作用,并且惯用的操作是点击,而不是映射。

标签: angular rxjs


【解决方案1】:
  • RxJS 的 map 函数将值映射到流中
  • Array 的map 函数遍历数组并映射数组中的值

这些是相似的,但不是一回事。在这种情况下,流中的值 一个数组。但它可以是任何东西。 RxJS 不知道你想遍历一个数组。

您可以将数组转换为流并通过 RxJS 映射其值,如下所示:

this.blogsFromAPI$ = this.blogService.getBlogs().pipe(
  pluck('stuff'),
  mergeMap(stuff => stuff),
  map(st => {
    st.url = "myurl" + st.alias;
    console.log(st );
    return st;
  })
);

现在,您的订阅者可以一次从您的数组中获取每个项目作为流。 您可以像这样转换回数组:

this.blogsFromAPI$ = this.blogService.getBlogs().pipe(
  pluck('stuff'),
  mergeMap(stuff => from(stuff).pipe(
    map((st => {
      st.url = "myurl" + st.alias;
      console.log(st );
      return st;
    }),
    toArray()
  ))
);

现在您将数组转换为流,映射其值,然后再转换回数组。这显然是相当浪费的。没有理由不能在 RxJS 流中使用 Array 的 map

this.blogsFromAPI$ = this.blogService.getBlogs().pipe(
  pluck('stuff'),
  map(stuff => stuff.map(st => {
    st.url = "myurl" + st.alias;
    console.log(st );
    return st;
  }))
);

现在你同时使用了 RxJS 的 map 数组的 map。这可能是您想要的。

最后,如果您想让这更简洁一点,您可以将pluckmap 合并为一个map

this.blogsFromAPI$ = this.blogService.getBlogs().pipe(
  map(blog => blog.stuff.map(st => {
    st.url = "myurl" + st.alias;
    console.log(st );
    return st;
  }))
);

这展示了 RxJS 的 map 被赋予一个对象而不是一个数组。


排序

如果您还想对数组进行排序,您可以在更新后的数组上使用 RxJS map 并创建一个新的排序数组,或者您可以只链接数组函数

this.blogsFromAPI$ = this.blogService.getBlogs().pipe(
  map(res => res.articles.map(a => {
    a.url = "http://globalfinancialdata.com/" + a.alias;
    return a;
  })), // <-- I noticed a missing ')' here. Gotta keep 'em lined up!
  map(art => art.sort((a, b) => 
    new Date(b.published_at).getTime() - new Date(a.published_at).getTime())
  ))
);

this.blogsFromAPI$ = this.blogService.getBlogs().pipe(
  map(res => 
    res.articles.map(a => {
      a.url = "http://globalfinancialdata.com/" + a.alias;
      return a;
    }).sort((a, b) =>
      new Date(b.published_at).getTime() - new Date(a.published_at).getTime())
    )
  )
);

【讨论】:

  • 出于好奇,我想对列表进行排序,但是当我尝试使用 .sort() 方法时,我在“stuff”下得到一个错误,即“property stuff doesn't exist on类型未知。'
  • 听起来您正在尝试取消引用未初始化的变量。如果没有看到您实际在做什么,就无法真正提供帮助。
  • 在您更新的帖子中,哪一行导致了错误?
  • 调用.sort()函数的那一行
  • 我更新了我的答案。看起来你只是缺少一个(
猜你喜欢
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
  • 2023-03-26
  • 2018-10-21
  • 2019-01-25
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
相关资源
最近更新 更多