Angular - 它是从服务发送请求比从组件发送请求更好?

问题描述 投票:0回答:2

我想知道我是否应该从角度服务发送请求?或者我应该直接从组件发送它?

第一种方法:

RestaurantService.ts

  getRestaurants(): Promise<_Restaurant[]> {
    return this.get("/restaurants").toPromise();
  };

Restaurants.component.ts

  loadRestaurants = async () => {
    try {
      this.restaurants  = await this.restaurantService.getRestaurants();
    } catch (exception) {
      console.log(JSON.stringify(exception, null, 2));
    }
  }

这意味着请求是通过组件触发的。

第二种方法:

RestaurantService.ts

  async getRestaurants(): Promise<_Restaurant[]> {
    try {
      const response: _Restaurant[] = await this.get("/restaurants").toPromise() as _Restaurant[];
      return response;
    } catch (exception) {
      throw new Error(exception);
    }
  };

Restaurants.component.ts

  loadRestaurants = async () => {
    try {
      this.restaurants  = await this.restaurantService.getRestaurants();
    } catch (exception) {
      console.log(JSON.stringify(exception, null, 2));
    }
  }

这意味着从服务中发出请求然后将响应作为承诺返回

那么最好的方法是什么?如果它是第二种方法,可以从服务中捕获错误并将其抛给组件?

javascript angular typescript service async-await
2个回答
1
投票

正如Angular doc所说,在服务中使用该逻辑更好,看看这个:

class Service {
  constructor(public http: HttpClient) { }

  getRestaurants(): Observable<Restaurant> {
    return this.http.get<{ /* Specify HTTP response schema */ }>(url).pipe(
      // Transformation to actual Restaurants at one place
      map(data => data.map(restaurant => new Restaurant()),
      // Handle error
      catchError(err => {
        logError(err);
        throw err;
        //  Or...
        return of([]); // Mock data not to crash app
      }),
      // If multiple subscription are made to same source, it won't do multiple http calls
      shareReply(1),
    );
  }
}
class Component {
  restaurants: Restaurant[] = [];

  ngOnInit(): void {
    // Prefered way
    this.restaurants$ = this.service.getRestaurants().pipe(
      // If, you pass error down, you'll be able to hendle it here...
      catchError(err => {
        return of([]);
      }),
    );
    // Alternative
    this.cleanUp = this.service.getRestaurants().subscribe(restaurants => {
      this.restaurants = restaurants;
    });
  }

  ngOnDestroy(): void {
    this.cleanUp.unsubscribe();
  }
}

HTML

<!-- Observable -->
<div *ngFor="let restaurant of restaurants$ | async">
  {{restaurant | json}}
</div>

<!-- Non-Observable -->
<div *ngFor="let restaurant of restaurants">
  {{restaurant | json}}
</div>

我已经将你的代码从promise转换为observable,因为observable是使用Angular的最大好处之一。可以取消Observables,在模板中可以很好地阅读,以及我可能会想到的其他许多其他内容。


Observable非常强大,您可以随时获得基于其他可观察信息的新信息。看看,它可能会给你一些想法......

interface ApiResponse<type> {
  awaitingNewValues: boolean;
  error: null | any;
  response: type;
}

class Service {
  currentRestaurantID = new BehaviourSubject(1);

  currentRestaurantInfo: Observable<ApiResponse<Restaurant>>;

  constructor(private http: HTTPClient) {
    let latestRestaurants: ApiResponse<Restaurant | undefined> = {
      awaitingNewValues: true,
      error: null,
      response: [],
    };
    currentRestaurantInfo = this.currentRestaurantID.pipe(
      switchMap(restaurantID => {
        return concat(
          // This will notify UI that we are requesting new values
          of(Object.assign({}, latestRestaurants, { awaitingNewValues: true })),
          // The actual call to API
          this.http.get(`${apiUrl}/${restaurantID}`).pipe(
            // Wrap response in metadata
            map(restaurant => {
              return {
                awaitingNewValues: false,
                error: null,
                response: restaurant,
              }
            }),
            // Notify UI of error & pass error
            catchError(err => {
              return of({
                awaitingNewValues: true,
                error: err,
                response: undefined,
              });
            }),
          ),
        );
      }),
      // Save last response to be used in next api call
      tap(restaurants => this.latestRestaurants = restaurants),
      // Prevent calling API too many times
      shareReplay(1),
    );
  }
}

0
投票

最佳做法是使用Observable

RestaurantService.ts

getRestaurants(): Observable<_Restaurant[]> {
    return this.get('/restaurants');
};

Restaurants.component.ts

import { Subscription } from 'rxjs';

sub: Subscription;

loadRestaurants(): void {
    this.sub = this.restaurantService.getRestaurants()
        .subscribe(result => {
            this.restaurants = result;
        }, exception => {
            console.log(exception);
        });
}

ngOnDestroy() {
    this.sub.unsubscribe();
}

如果您需要修改响应,则应在服务中使用pipe方法。

© www.soinside.com 2019 - 2024. All rights reserved.