首页 > 解决方案 > 创建通用方法的 Angular 最佳实践

问题描述

我正在使用 HttpClient 在 Angular 中设计 Api 端点。这是一个将处理所有 Rest 调用的单个服务类,它将从其他服务类(当前正在进行 Rest 调用)中调用。

制作通用 Rest 方法的最佳实践是什么。

getApi(url: string, options?: object): Observable<any> {
    return this.http.get<any>(url, options).pipe(
      catchError((error: HttpErrorResponse) => {
        return throwError(error);
    })
  )
}

或者

getApi<T>(url: string, options?: object): Observable<T> {
    return this.http.get<T>(url, options).pipe(
      catchError((error: HttpErrorResponse) => {
        return throwError(error);
    })
  )
}

上述任何一个都能够处理:HttpEvent、HttpResponse 或其他此类响应吗?

我应该采取多种方法来处理吗?

标签: angulartypescriptrxjs

解决方案


请注意,答案非常基于意见。

在我展示我的解决方案之前,我想分享它下面的想法。因此,当我使用 TS 时,我希望拥有尽可能严格的类型。因此,在这种情况下,使用any,object或类似的东西会分散注意力。我还想避免任何额外的类型转换,因为它会在某处导致错误。

幸运的是,TS 非常聪明地帮助我实现了这个目标,因为它可以根据使用情况识别类型。

基于此,我们可以构建如下内容:

一个非常通用的类,可以满足我们的一切需求(它可以通过传递参数来扩展,以获取、记录、计数器任何你需要的东西)

class HttpService {
    get<TData, TResult>(url: string, data?: TData): Promise<TResult> {
        return fetch(url, data)
            .then(x => x.json())
            .catch((err) => console.log(err));
    }
}

但是这个类不应该直接使用。我建议创建一个更严格和更专业的服务,该服务将隔离获取逻辑并提供严格的类型而不是泛型。

type User = {
    name: string;
}

class MyDataService {

    constructor(private readonly _transportService: HttpService) { }
    fetchUserInfo(userId: number): Promise<User> {
        return this._transportService.get('/some/url', userId);
    }
}

现在,我可以使用 MyDataService 而无需任何类型转换和类型猜测。另一个好处是这项服务非常容易测试,因为您可以根据需要替换传输模块。

希望我的回答对你有所帮助。


推荐阅读