通用HTTP服务reactjs

2cmtqfgy  于 8个月前  发布在  React
关注(0)|答案(1)|浏览(74)

我是reactjs的新手,我想做一些服务来与API交互,我想让http服务更通用,这样它就可以在其他组件中使用。

import axios from "axios";
import { CanceledError } from "axios";

export default axios.create({
  baseURL: "https://jsonplaceholder.typicode.com/",
});

export { CanceledError };

字符串
首先,我为API调用创建baseURL,并创建一个包含方法2(如get、post和put)的通用http服务

import apiClient from "./api-client";

interface Entity {
  id: number;
  name: string;
}

class HttpServices {
  endpoint: string;
  constructor(endpoint: string) {
    this.endpoint = endpoint;
  }
  getAll<T>() {
    const controller = new AbortController();
    const request = apiClient.get<T[]>(this.endpoint, {
      signal: controller.signal,
    });
    return { request, cancel: () => controller.abort() };
  }

  delete(id: number) {
    return apiClient.delete(this.endpoint + "/" + id);
  }

  add<T>(entity: T) {
    return apiClient.post(this.endpoint, entity);
  }

  update<T extends Entity>(updatedEntity: T) {
    return apiClient.patch(
      this.endpoint + "/" + updatedEntity.id,
      updatedEntity
    );
  }
}

//export default new HttpServices();

const create = (endpoint: string) => new HttpServices(endpoint);

export default create;


然后我使用通用的http服务来处理用户,并将用户的端点

import create from "./http-service";
export interface User {
  id: number;
  name: string;
}

export default create("users");


并且我使用表单更新用户组件中的用户服务

const updateUser = (users: User) => {
    const originalUser = [...user];
    const updatedUser = { ...users, name: users.name + "!" };
    setUsers(user.map((u) => (u.id === users.id ? updatedUser : u)));

    userServices.update(updatedUser).catch((err) => {
      setErrors(err.message);
      setUsers(originalUser);
    });
  };


希望你们能理解我的解释
所以,问题是...
如果您在通用http服务中看到使用接口Entity来扩展包含id和name的通用占位符保持器数据类型,该数据类型与用户服务中的用户接口相同,那么如果我想使用具有id,name和description的类别接口来创建类别服务,该怎么办?如果我在Entity接口中添加了描述,当我在updateUser方法“Argument of type”{ name:string; id:number;“}"不能分配给类型为”“的参数。”我怎样才能使接口更灵活或更容易接受?或者对此有什么建议?
我只是想知道我问题的解决办法

qrjkbowd

qrjkbowd1#

我想你正在寻找这样的解决方案:

  • 首先,在基础HttpService中,您需要完全满足axios内置类型,以使您的基础服务更加灵活。
  • 其次,您需要创建一些ApiServiceFactory,这些ApiServiceFactory将使用不同的axios设置(如headersbaseUrl)示例化您的实体特定服务,如UserServiceAuthServiceCategoryService
  • 如果你的实体url有相同的起始路径(通常),你可以在基类constructor{baseUrl: 'https://myapi.com/${baseUrl}'})中硬编码起始路径。然后ApiServiceFactory('user')将示例化axios与baseUrl: 'https://myapi.com/user';而ApiServiceFactory('category')导致axios与baseUrl: 'https://myapi.com/category'等等。
  • 但如果你的实体url没有相同的起始路径,例如,Userhttps://api1.com/user相关,Categoryhttps://someotherapi.com/v1/en/category相关。你需要在基本HttpService构造函数中保留baseUrl以清空并在工厂中使用CategoryService extends ApiServiceFactory('https://someotherapi.com/v1/en/category')指定完整的url
  • 第三,您需要仅在实体特定的服务中指定某些(具体)类型,在我的示例中,它是UserUpdateUserCategoryCreateCategoryManyIdRecord<SignUpFieldsEnum, string>Record<SignInFieldsEnum, string>

基本ApiService类:

import axios from 'axios';
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
# ... List of imports my own types ....

export class ApiService {
  api: AxiosInstance;

  constructor(baseUrl = '') {
    this.api = axios.create({
      baseURL: `https://jsonplaceholder.typicode.com/${baseUrl}`,
    });
  }

  protected async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    const { data } = await this.api.get<T>(url, config);
    return data;
  }

  protected async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    const { data: d } = await this.api.put<T>(url, data, config);
    return d;
  }

  protected async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    const { data: d } = await this.api.post<T>(url, data, config);
    return d;
  }

  protected async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    const { data } = await this.api.delete<T>(url, config);
    return data;
  }
}

字符串
UserService类:

class UserService extends ApiServiceFactory('user') {
  profile(): Promise<User> {
    return this.get<User>('');
  }

  update(data: Partial<UpdateUser>): Promise<boolean> {
    return this.put<boolean>('');
  }
}


AuthService类:

class AuthService extends ApiServiceFactory('auth') {
  signIn(data: Record<SignInFieldsEnum, string>): Promise<boolean> {
    return this.put<boolean>('sign-in', data);
  }

  signUp(data: Record<SignUpFieldsEnum, string>): Promise<boolean> {
    return this.post<boolean>('sign-up', data);
  }

  logout(): Promise<boolean> {
    return this.put<boolean>('logout');
  }
}


CategoryService类:

class CategoryService extends ApiServiceFactory('category') {
  async list(params: PaginationQuery): Promise<Paginated<Category>> {
    return this.get<Paginated<Category>>('', { params });
  }

  create(data: CreateCategory): Promise<boolean> {
    return this.post<boolean>('', data);
  }

  update(id: number, data: CreateCategory): Promise<boolean> {
    return this.put<boolean>(`/${id}`, data);
  }

  remove(data: ManyId): Promise<boolean> {
    return this.delete<boolean>('', { data });
  }
}

相关问题