首页 > 解决方案 > 为什么在这段代码中使用 RxJS pipe() 操作符来封装单个 map() 操作符而不是链接多个 RxJS 操作符?

问题描述

我不太喜欢 RxJs。我正在关注基于 Angular+RxJS 的 Angular 视频课程,但我有以下疑问。基本上,它创建了一个服务类,该类调用返回 JSON 的 REST API,如下所示:

{
   "payload":[
      {
     "id":1,
     "description":"Serverless Angular with Firebase Course",
     "longDescription":"Serveless Angular with Firestore, Firebase Storage & Hosting, Firebase Cloud Functions & AngularFire",
     "iconUrl":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/serverless-angular-small.png",
     "lessonsCount":10,
     "category":"BEGINNER",
     "seqNo":6,
     "url":"serverless-angular",
     "price":50
      },
      {
     "id":2,
     "description":"Angular Core Deep Dive",
     "longDescription":"A detailed walk-through of the most important part of Angular - the Core and Common modules",
     "iconUrl":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/angular-core-in-depth-small.png",
     "lessonsCount":10,
     "category":"BEGINNER",
     "seqNo":3,
     "url":"angular-core-course",
     "price":50
      },
      {
     "id":3,
     "description":"RxJs In Practice Course",
     "longDescription":"Understand the RxJs Observable pattern, learn the RxJs Operators via practical examples",
     "iconUrl":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/rxjs-in-practice-course.png",
     "courseListIcon":"https://angular-academy.s3.amazonaws.com/main-logo/main-page-logo-small-hat.png",
     "category":"BEGINNER",
     "lessonsCount":10,
     "seqNo":2,
     "url":"rxjs-course",
     "price":50
      },
      {
     "id":4,
     "description":"NgRx (with NgRx Data) - The Complete Guide",
     "longDescription":"Learn the modern Ngrx Ecosystem, including NgRx Data, Store, Effects, Router Store, Ngrx Entity, and Dev Tools.",
     "iconUrl":"https://angular-university.s3-us-west-1.amazonaws.com/course-images/ngrx-v2.png",
     "category":"BEGINNER",
     "lessonsCount":10,
     "seqNo":1,
     "url":"ngrx-course",
     "promo":false,
     "price":50
      },
      {
     "id":5,
     "description":"Angular for Beginners",
     "longDescription":"Establish a solid layer of fundamentals, learn what's under the hood of Angular",
     "iconUrl":"https://angular-academy.s3.amazonaws.com/thumbnails/angular2-for-beginners-small-v2.png",
     "courseListIcon":"https://angular-academy.s3.amazonaws.com/main-logo/main-page-logo-small-hat.png",
     "category":"BEGINNER",
     "lessonsCount":10,
     "seqNo":4,
     "url":"angular-for-beginners",
     "price":50
      },
      {
     "id":6,
     "description":"Angular Security Course - Web Security Fundamentals",
     "longDescription":"Learn Web Security Fundamentals and apply them to defend an Angular / Node Application from multiple types of attacks.",
     "iconUrl":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/security-cover-small-v2.png",
     "courseListIcon":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/lock-v2.png",
     "category":"ADVANCED",
     "lessonsCount":11,
     "seqNo":9,
     "url":"angular-security-course",
     "price":50
      },
      {
     "id":7,
     "description":"Angular PWA - Progressive Web Apps Course",
     "longDescription":"Learn Angular Progressive Web Applications, build the future of the Web Today.",
     "iconUrl":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/angular-pwa-course.png",
     "courseListIcon":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/alien.png",
     "category":"ADVANCED",
     "lessonsCount":8,
     "seqNo":10,
     "url":"angular-pwa-course",
     "price":50
      },
      {
     "id":8,
     "description":"Angular Advanced Library Laboratory: Build Your Own Library",
     "longDescription":"Learn Advanced Angular functionality typically used in Library Development. Advanced Components, Directives, Testing, Npm",
     "iconUrl":"https://angular-academy.s3.amazonaws.com/thumbnails/advanced_angular-small-v3.png",
     "courseListIcon":"https://angular-academy.s3.amazonaws.com/thumbnails/angular-advanced-lesson-icon.png",
     "category":"ADVANCED",
     "seqNo":11,
     "url":"angular-advanced-course",
     "price":50
      },
      {
     "id":9,
     "description":"The Complete Typescript Course",
     "longDescription":"Complete Guide to Typescript From Scratch: Learn the language in-depth and use it to build a Node REST API.",
     "iconUrl":"https://angular-academy.s3.amazonaws.com/thumbnails/typescript-2-small.png",
     "courseListIcon":"https://angular-academy.s3.amazonaws.com/thumbnails/typescript-2-lesson.png",
     "category":"BEGINNER",
     "seqNo":12,
     "url":"typescript-course",
     "price":50
      },
      {
     "id":11,
     "description":"Angular Material Course",
     "longDescription":"Build Applications with the official Angular Widget Library",
     "iconUrl":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/material_design.png",
     "category":"BEGINNER",
     "seqNo":14,
     "url":"angular-material-course",
     "price":50
      },
      {
     "id":12,
     "description":"Angular Testing Course",
     "longDescription":"In-depth guide to Unit Testing and E2E Testing of Angular Applications",
     "iconUrl":"https://s3-us-west-1.amazonaws.com/angular-university/course-images/angular-testing-small.png",
     "category":"BEGINNER",
     "seqNo":5,
     "url":"angular-testing-course",
     "lessonsCount":10,
     "promo":false,
     "price":50
      },
      {
     "id":14,
     "description":"NestJs In Practice (with MongoDB)",
     "longDescription":"Build a modern REST backend using Typescript, MongoDB and the familiar Angular API.",
     "iconUrl":"https://angular-university.s3-us-west-1.amazonaws.com/course-images/nestjs-v2.png",
     "category":"BEGINNER",
     "lessonsCount":10,
     "seqNo":8,
     "url":"nestjs-course",
     "promo":false,
     "price":50
      },
      {
     "id":16,
     "description":"Stripe Payments In Practice",
     "longDescription":"Build your own ecommerce store & membership website with Firebase, Stripe and Express",
     "iconUrl":"https://angular-university.s3-us-west-1.amazonaws.com/course-images/stripe-course.jpg",
     "lessonsCount":10,
     "category":"BEGINNER",
     "seqNo":7,
     "url":"stripe-course",
     "price":50
      },
      {
     "id":17,
     "description":"Reactive Angular Course",
     "longDescription":"How to build Angular applications in Reactive style using plain RxJs - Patterns and Anti-Patterns",
     "iconUrl":"https://angular-university.s3-us-west-1.amazonaws.com/course-images/reactive-angular-course.jpg",
     "courseListIcon":"https://angular-academy.s3.amazonaws.com/main-logo/main-page-logo-small-hat.png",
     "category":"BEGINNER",
     "lessonsCount":10,
     "seqNo":0,
     "url":"reactive-angular-course",
     "price":50
      }
   ]
}

如您所见,它包含一个包含 n 个对象的有效负载属性。本教程显示,从发出此有效负载属性的 Observable 开始,它将返回另一个仅发出数组的 Observable。

这是建议的解决方案:

@Injectable({
  providedIn: 'root'
})
export class CoursesService {

  constructor(private http:HttpClient) {}

  loadedAllCourses(): Observable<Course[]> {
    // The obsarvable return a JSON containing the "payload" property containing the array
    //return this.http.get<Course[]>("/api/courses");
    return this.http.get<Course[]>("/api/courses")
          .pipe(
            map(res => res["payload"])
          );


  }

}

现在我知道map()运算符在 Observable 上工作并返回另一个 Observable “修改”通过传递给原始 Observable 的箭头函数(在这种情况下,我正在访问API 调用响应的有效负载字段的内容,我我正在创建一个仅包含有效负载字段内容的新 Observable。很清楚。

我无法理解的是:为什么这个map()运算符是在pipe()运算符中定义的。根据我阅读官方文档的理解,pipe()运算符用于以声明方式链接多个运算符(例如:应用 OPERATOR 1,在 OPERATOR 1(即 Observable)的输出上应用 OPERATOR 2 并返回另一个可观察等。

这个推理正确吗?在前一种情况下,我只有一个map()运算符,所以理论上我可以直接在get()方法返回的 Observable 上使用map()运算符(直接在包含 API 响应的 Observable 上)。这样对吗?

为什么在本课程中,当只应用一个运算符时,教员总是使用pipe()运算符?(如前一种情况)。这是一种约定还是“错误”?

标签: typescriptrxjs

解决方案


在本课程中,讲师始终使用 pipe() 运算符,因为从 RxJs 6 开始,他们使用可管道运算符,这来自官方文档 - https://rxjs.dev/guide/v6/pipeable-operators

关于您使用地图的方式,“pluck”运算符似乎更适合您的情况:

   this.http.get<Course[]>("/api/courses")
    .pipe(
        pluck("payload")
    );

推荐阅读