繁体   English   中英

Angular:这是重构“.subscribe()”中代码的最佳方式

[英]Angular: Which is the best way of refactoring the code inside ".subscribe()"

假设我有这样的组件

原始代码:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<pre>{{ response | json }}</pre>`,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  constructor(private _http: HttpClient) {
    this.fetchUsers();
  }

  response!: any;

  fetchUsers() {
    this._http.get(`https://jsonplaceholder.typicode.com/users`).subscribe(
      (resp) => {
        console.log(resp);
        this.response = resp;
      },
      (err) => {
        console.error(err);
        this.response = err;
      },
      () => {
        console.log('Subscription Complete');
      }
    );
  }
}

我有以下方法来重构上面的代码......

重构方法一:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<pre>{{ response | json }}</pre>`,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  constructor(private _http: HttpClient) {
    this.fetchUsers();
  }

  response!: any;

  onSubscribe = (resp: any) => {
    console.log(resp);
    this.response = resp;
  };

  onError = (err: any) => {
    console.error(err);
    this.response = err;
  };

  onCompletion = () => {
    console.log('Subscription Complete');
  };

  fetchUsers() {
    this._http
      .get(`https://jsonplaceholder.typicode.com/users`)
      .subscribe(this.onSubscribe, this.onError, this.onCompletion);
  }
}

重构方法 2:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<pre>{{ response | json }}</pre>`,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  constructor(private _http: HttpClient) {
    this.fetchUsers();
  }

  response!: any;

  onSubscribe(resp: any) {
    console.log(resp);
    this.response = resp;
  }

  onError(err: any) {
    console.error(err);
    this.response = err;
  }

  onCompletion() {
    console.log('Subscription Complete');
  }

  fetchUsers() {
    this._http.get(`https://jsonplaceholder.typicode.com/users`).subscribe(
      (resp) => this.onSubscribe(resp),
      (err) => this.onError(err),
      () => this.onCompletion()
    );
  }
}

重构方法 3:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<pre>{{ response | json }}</pre>`,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  constructor(private _http: HttpClient) {
    this.fetchUsers();
  }

  response!: any;

  fetchUsers() {
    this._http.get(`https://jsonplaceholder.typicode.com/users`).subscribe({
      next: (resp: any) => {
        console.log(resp);
        this.response = resp;
      },
      error: (err: any) => {
        console.error(err);
        this.response = err;
      },
      complete: () => {
        console.log('Subscription Complete');
      },
    });
  }
}

重构方法 4:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<pre>{{ response | json }}</pre>`,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  constructor(private _http: HttpClient) {
    this.fetchUsers();
  }

  response!: any;

  onSubscribe = (resp: any) => {
    console.log(resp);
    this.response = resp;
  };

  onError = (err: any) => {
    console.error(err);
    this.response = err;
  };

  onCompletion = () => {
    console.log('Subscription Complete');
  };

  fetchUsers() {
    this._http.get(`https://jsonplaceholder.typicode.com/users`).subscribe({
      next: this.onSubscribe,
      error: this.onError,
      complete: this.onCompletion,
    });
  }
}

重构方法 5:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<pre>{{ response | json }}</pre>`,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  constructor(private _http: HttpClient) {
    this.fetchUsers();
  }

  response!: any;

  onSubscribe(resp: any) {
    console.log(resp);
    this.response = resp;
  }

  onError(err: any) {
    console.error(err);
    this.response = err;
  }

  onCompletion() {
    console.log('Subscription Complete');
  }

  fetchUsers() {
    this._http.get(`https://jsonplaceholder.typicode.com/users`).subscribe({
      next: (resp: any) => this.onSubscribe(resp),
      error: (err: any) => this.onError(err),
      complete: () => this.onCompletion(),
    });
  }
}

现在的问题是

考虑性能(首先是可读性)——哪个是最好的选择?

  1. 重构方法 1?
  2. 重构方法 2?
  3. 重构方法 3?
  4. 重构方法 4?
  5. 重构方法 5?
  6. 原始代码?

我认为最好的方法是数字 4,原因如下:

谈到可读性,您在订阅中传递三个 arguments 的方式(下一个、错误、完成)实际上已被 RxJS 弃用,因为 function arguments 会导致代码难以阅读。 你可以在这里读更多关于它的内容

相反,RxJS 建议您使用 JS 882829995402888 作为参数,您可以在其中定义不同回调的代码

({next: () =>{}, error: () =>{}, complete: () =>{})

将代码分成函数可以帮助您使其更清晰易读。

谈论性能,如果您将 JS object 之类的参数传递给订阅 RxJS,则将空的 function 传递给其中一个回调,而不是您自己执行。

就个人而言,我会重构为声明式方法

  1. 创建一个服务来封装所有的数据访问。
  2. 在服务中,定义一个变量(不是方法)来管理从 http get 返回的 Observable。
  3. 在组件中,定义一个变量(不是构造函数或生命周期钩子)来管理从服务返回的 Observable
  4. 在模板中使用async pipe。

示例服务:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { tap } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class UserService {
  users$ = this.http
    .get(`https://jsonplaceholder.typicode.com/users`)
    .pipe(tap((response) => console.log(response)));

  constructor(private http: HttpClient) {}

  fetchUsers() {}
}

示例组件/模板

import { Component } from '@angular/core';
import { catchError } from 'rxjs';
import { UserService } from './user.service';

@Component({
  selector: 'my-app',
  template: `<pre>{{ users$ | async | json }}</pre>`,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  errorMessage = '';

  users$ = this.userService.users$.pipe(
    catchError(err => this.errorMessage = err)
  )

  constructor(private userService: UserService) { }

}

有关此声明模式的更多信息,请参阅: https://youtu.be/0XPxUa8u-LY

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM