问题描述
遇到一些问题,试图提出一种编码方法。首先,我要说这不是我的强项,也没有尝试过类似的方法。
目标:为客户端创建包装API库。它应该公开一种使用basePath实例化lib的方法/类,然后公开其名称空间的对象/类及其上的调用内部API的方法,因此,使用者只需传递每个API调用所需的数据即可。简单,因此我们通常可以处理诸如错误之类的事情。
我知道我在这里无法工作-但这主要是为了了解我希望达到的目标。
我的问题是类似的
感谢所有帮助和建议。
abstract class Base {
constructor(private basePath: string = '') {}
async get<T>(endpoint: string,config?: Requestinit | undefined): Promise<T> {
const response = await fetch(this.basePath + endpoint,config);
return response.json();
}
// ... other methods that would be available
}
// Exported to the consumer for ease of use. Others Could be `Comments.postNewComment({user,data})`
class Posts extends Base {
getAllPosts() {
return this.get<PostsData>('/posts')
}
}
// In the main index file for lib,it would export all the classes with available API methods (such as Posts,Auth,Comments etc) that the consumer would be able to use.
// Issue comes up when creating an instance of these because it would require the basePath again
export { Posts: new Posts(),Comments: new Comments() };
// Ideal usage: Main file of the app:
import LibName from 'lib-name'
new LibName({ basePath: 'api.whatever' }) // Left out re: brevity,but would be the class where we instantiate the basePath,and anything else
// In other locations through the app,be able to call the varIoUs methods from different sections (Auth.login,Comments.addNewComment etc)
import { Posts } from 'lib-name';
Posts.getAllPosts();
我一开始就遵循this article,但这的最后一个示例在一个导出(DevToClient.X)下公开了所有方法,而我希望将它们命名为其相应的父对象的命名空间。
解决方法
为什么不为依赖于对象 Endpoint
的类型的 T
创建一个可实例化的类?
class Endpoint<T extends {id: string},Creatable = T> {
constructor(private endpointPath: string) {}
async get(id: string,config?: RequestInit | undefined): Promise<T> {
const response = await fetch(this.endpointPath + '/' + id,config);
return response.json();
}
// stubs of sample methods
async getAll( someFilters?: any ): Promise<T[]> {}
async update(changes: Partial<T> & {id: string}): Promise<T> {}
async createNew( object: Creatable ): Promise<T> {}
}
我还添加了第二个可选参数 Creatable
,因为创建请求不包含所创建对象的每个属性是正常的。例如,id
和 date
可能是由服务器设置的。
我们不会导出 Endpoint
类,而是会为不同类型创建实例并导出它们。
export const Posts = new Endpoint<PostObject>('/posts');
export const Comments = new Endpoint<Comments>('/comments');
你可以这样使用它:
import {Posts} from 'some-lib'
const post = Posts.get("321"); // Promise<PostObject>
// the arguments depend on your partuicular api structure
const latest = Posts.getAll({limit: 10,sort: 'date'}); // Promise<PostObject[]>
const updated = Posts.update({id: "123",title: "New Title"}); // Promise<PostObject>
如果您想支持更高级的配置,这些配置在端点之间有所不同,例如验证,这就是您可以使用组合的地方。 Endpoint
可以在构造函数中接受某种类型的 config
对象或类。