Repository navigation
Expand file tree
/
Copy pathapi.js
More file actions
44 lines (42 loc) · 1.97 KB
/
Copy pathapi.js
File metadata and controls
44 lines (42 loc) · 1.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
export class ApiError extends Error {
constructor(message,status=0,generation) {super(message);this.status=status;this.sessionGeneration=generation;}
}
export class StaleResponse extends Error {
constructor() {super('账号已切换,忽略旧请求');this.name='StaleResponse';}
}
export class API {
constructor(transport=globalThis.fetch.bind(globalThis)) {
this.transport=transport;
this.csrf='';
this.generation=0;
}
clear() {this.csrf='';this.generation++;}
assertCurrent(result) {if(result._sessionGeneration!==this.generation) throw new StaleResponse();}
async request(method,path,payload) {
const generation=this.generation;
const current=()=>{if(generation!==this.generation) throw new StaleResponse();};
const headers={Accept:'application/json'};
if (payload !== undefined) headers['Content-Type']='application/json';
if (!['GET','HEAD'].includes(method) && this.csrf) headers['X-CSRF-Token']=this.csrf;
let response;
try {
response=await this.transport(path,{method,headers,credentials:'same-origin',...(payload!==undefined ? {body:JSON.stringify(payload)} : {})});
} catch {
current();
throw new ApiError('无法连接服务器,请检查网络后重试',0,generation);
}
let result;
try {result=await response.json();} catch {current();throw new ApiError('服务器响应异常,请稍后重试',response.status,generation);}
current();
if (!response.ok) {
const detail=result.detail;
const message=typeof detail==='string' ? detail : Array.isArray(detail) ? detail[0]?.msg?.replace(/^Value error, /,'') : '';
throw new ApiError(message || '操作未完成,请稍后重试',response.status,generation);
}
if (path==='/api/auth/login' || path==='/api/auth/register') this.generation++;
if (result.csrfToken) this.csrf=result.csrfToken;
Object.defineProperty(result,'_sessionGeneration',{value:this.generation});
return result;
}
}
export const api=new API();