@jolibox/implement 1.1.9 → 1.1.10-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,19 +20,52 @@ const timeoutFn = (ms: number) => {
20
20
 
21
21
  (AbortSignal as any).timeout ??= timeoutFn;
22
22
 
23
- export class JoliboxHttpClient implements IHttpClient {
23
+ export class HttpClientManager {
24
+ private static _instance: HttpClientManager;
25
+ private httpClients = new WeakSet<JoliboxHttpClient>();
26
+ private networkRequests: boolean[] = [];
27
+ private maxRequestsToTrack = 20;
28
+
29
+ static getInstance(): HttpClientManager {
30
+ if (!HttpClientManager._instance) {
31
+ HttpClientManager._instance = new HttpClientManager();
32
+ }
33
+ return HttpClientManager._instance;
34
+ }
35
+
36
+ create(config?: IHttpClientInitParams): JoliboxHttpClient {
37
+ const client = new JoliboxHttpClient(config);
38
+ HttpClientManager.getInstance().httpClients.add(client);
39
+ return client;
40
+ }
41
+
42
+ recordNetworkRequest(success: boolean): void {
43
+ this.networkRequests.push(success);
44
+ if (this.networkRequests.length > this.maxRequestsToTrack) {
45
+ this.networkRequests.shift();
46
+ }
47
+ }
48
+
49
+ getNetworkStatus(): boolean {
50
+ if (this.networkRequests.length === 0) {
51
+ return true;
52
+ }
53
+
54
+ const successCount = this.networkRequests.filter((success) => success).length;
55
+ const successRate = successCount / this.networkRequests.length;
56
+
57
+ return successRate >= 0.6;
58
+ }
59
+ }
60
+
61
+ class JoliboxHttpClient implements IHttpClient {
24
62
  private baseUrl: string;
25
- private xua = xUserAgent();
63
+ protected xua = xUserAgent();
26
64
 
27
65
  private getJoliSource = () => {
28
66
  return context.joliSource;
29
67
  };
30
68
 
31
- // private getApiBaseURL = () => {
32
- // const urlParams = new URLSearchParams(window.location.search);
33
- // return urlParams.get('apiBaseURL') ?? null;
34
- // };
35
-
36
69
  constructor(config?: IHttpClientInitParams) {
37
70
  const defaultUrl = context.testMode ? 'https://stg-api.jolibox.com' : 'https://api.jolibox.com';
38
71
  this.baseUrl = config?.baseUrl ?? defaultUrl;
@@ -46,26 +79,34 @@ export class JoliboxHttpClient implements IHttpClient {
46
79
  timeout?: number;
47
80
  }
48
81
  ) {
49
- const { query, timeout } = configs ?? {};
50
- let { headers } = configs ?? {};
51
- const searchParams = query ? new URLSearchParams(query) : null;
52
- const search = searchParams?.toString();
53
- const url = `${this.baseUrl}${path}${search ? `?${search}` : ''}`;
54
- const xua = this.xua;
55
- const joliSource = this.getJoliSource();
56
- headers = Object.assign(
57
- {},
58
- headers ?? {},
59
- xua ? { 'x-user-agent': xua } : {},
60
- joliSource ? { 'x-joli-source': joliSource } : {}
61
- );
62
- const response = await fetch(url, {
63
- method: 'GET',
64
- headers,
65
- credentials: 'include',
66
- signal: timeoutFn(timeout ?? 30000)
67
- });
68
- return (await response.json()) as T;
82
+ try {
83
+ const { query, timeout } = configs ?? {};
84
+ let { headers } = configs ?? {};
85
+ const searchParams = query ? new URLSearchParams(query) : null;
86
+ const search = searchParams?.toString();
87
+ const url = `${this.baseUrl}${path}${search ? `?${search}` : ''}`;
88
+ const xua = this.xua;
89
+ const joliSource = this.getJoliSource();
90
+ headers = Object.assign(
91
+ {},
92
+ headers ?? {},
93
+ xua ? { 'x-user-agent': xua } : {},
94
+ joliSource ? { 'x-joli-source': joliSource } : {}
95
+ );
96
+ const response = await fetch(url, {
97
+ method: 'GET',
98
+ headers,
99
+ credentials: 'include',
100
+ signal: timeoutFn(timeout ?? 30000)
101
+ });
102
+
103
+ HttpClientManager.getInstance().recordNetworkRequest(true);
104
+
105
+ return (await response.json()) as T;
106
+ } catch (error) {
107
+ HttpClientManager.getInstance().recordNetworkRequest(false);
108
+ throw error;
109
+ }
69
110
  }
70
111
 
71
112
  async post<T = any>(
@@ -77,62 +118,65 @@ export class JoliboxHttpClient implements IHttpClient {
77
118
  timeout?: number;
78
119
  }
79
120
  ) {
80
- const { data, query, timeout } = configs ?? {};
81
- let { headers } = configs ?? {};
82
- const searchParams = query ? new URLSearchParams(query) : null;
83
- const search = searchParams?.toString();
84
- const url = `${this.baseUrl}${path}${search ? `?${search}` : ''}`;
85
- const xua = this.xua;
86
- const joliSource = this.getJoliSource();
87
- headers = Object.assign(
88
- {},
89
- headers ?? {},
90
- { 'Content-Type': 'application/json' },
91
- xua ? { 'x-user-agent': xua } : {},
92
- joliSource ? { 'x-joli-source': joliSource } : {}
93
- );
94
- const response = await fetch(url, {
95
- method: 'POST',
96
- headers,
97
- body: JSON.stringify(data),
98
- signal: timeoutFn(timeout ?? 30000),
99
- credentials: 'include'
100
- });
101
-
102
- const responseContentType = response.headers.get('content-type');
103
-
104
- // return blob
105
- if (responseContentType?.includes('application/octet-stream')) {
106
- try {
107
- return response.blob() as unknown as T;
108
- } catch (e) {
109
- return (await response.arrayBuffer()) as unknown as T;
121
+ try {
122
+ const { data, query, timeout } = configs ?? {};
123
+ let { headers } = configs ?? {};
124
+ const searchParams = query ? new URLSearchParams(query) : null;
125
+ const search = searchParams?.toString();
126
+ const url = `${this.baseUrl}${path}${search ? `?${search}` : ''}`;
127
+ const xua = this.xua;
128
+ const joliSource = this.getJoliSource();
129
+ headers = Object.assign(
130
+ {},
131
+ headers ?? {},
132
+ { 'Content-Type': 'application/json' },
133
+ xua ? { 'x-user-agent': xua } : {},
134
+ joliSource ? { 'x-joli-source': joliSource } : {}
135
+ );
136
+ const response = await fetch(url, {
137
+ method: 'POST',
138
+ headers,
139
+ body: JSON.stringify(data),
140
+ signal: timeoutFn(timeout ?? 30000),
141
+ credentials: 'include'
142
+ });
143
+
144
+ HttpClientManager.getInstance().recordNetworkRequest(true);
145
+
146
+ const responseContentType = response.headers.get('content-type');
147
+
148
+ if (responseContentType?.includes('application/octet-stream')) {
149
+ try {
150
+ return response.blob() as unknown as T;
151
+ } catch (e) {
152
+ return (await response.arrayBuffer()) as unknown as T;
153
+ }
110
154
  }
111
- }
112
155
 
113
- // return form data
114
- if (
115
- responseContentType?.includes('multipart/form-data') ||
116
- responseContentType?.includes('application/x-www-form-urlencoded')
117
- ) {
118
- try {
119
- return response.formData() as unknown as T;
120
- } catch (e) {
121
- return (await response.text()) as unknown as T;
156
+ if (
157
+ responseContentType?.includes('multipart/form-data') ||
158
+ responseContentType?.includes('application/x-www-form-urlencoded')
159
+ ) {
160
+ try {
161
+ return response.formData() as unknown as T;
162
+ } catch (e) {
163
+ return (await response.text()) as unknown as T;
164
+ }
122
165
  }
123
- }
124
166
 
125
- // return json
126
- if (responseContentType?.includes('application/json')) {
127
- try {
128
- return (await response.json()) as T;
129
- } catch (e) {
130
- return (await response.text()) as unknown as T;
167
+ if (responseContentType?.includes('application/json')) {
168
+ try {
169
+ return (await response.json()) as T;
170
+ } catch (e) {
171
+ return (await response.text()) as unknown as T;
172
+ }
131
173
  }
132
- }
133
174
 
134
- // return text
135
- return response as unknown as T;
175
+ return response as unknown as T;
176
+ } catch (error) {
177
+ HttpClientManager.getInstance().recordNetworkRequest(false);
178
+ throw error;
179
+ }
136
180
  }
137
181
 
138
182
  async put<T>(
@@ -163,14 +207,15 @@ export class JoliboxHttpClient implements IHttpClient {
163
207
  method: 'PUT',
164
208
  headers,
165
209
  credentials: 'include',
166
- body: JSON.stringify(data ?? {}) // 将数据转换为 JSON 字符串
210
+ body: JSON.stringify(data ?? {})
167
211
  });
168
212
 
169
- // 检查响应状态
170
213
  if (!response.ok) {
214
+ HttpClientManager.getInstance().recordNetworkRequest(false);
171
215
  throw new Error(`HTTP error! status: ${response.status}`);
172
216
  }
173
217
 
218
+ HttpClientManager.getInstance().recordNetworkRequest(true);
174
219
  const result = (await response.json()) as T;
175
220
  return result;
176
221
  } catch (error) {
@@ -182,4 +227,4 @@ export class JoliboxHttpClient implements IHttpClient {
182
227
 
183
228
  window.JoliboxHttpClient = JoliboxHttpClient;
184
229
 
185
- export default JoliboxHttpClient;
230
+ export const httpClientManager = HttpClientManager.getInstance();
@@ -1,7 +1,6 @@
1
1
  import { context } from '@/common/context';
2
- import { logger } from '@jolibox/common';
3
2
  import { EventTracker } from '@/common/report';
4
- import JoliboxHttpClient from '@/h5/http';
3
+ import { httpClientManager } from '@/h5/http';
5
4
 
6
5
  export class H5EventTracker extends EventTracker {
7
6
  private hostToApiMap: Record<string | 'default', { test: string; prod: string }> = {
@@ -24,15 +23,19 @@ export class H5EventTracker extends EventTracker {
24
23
  return context.testMode ?? false ? api.test : api.prod;
25
24
  }
26
25
 
27
- private httpClient = new JoliboxHttpClient({
26
+ private httpClient = httpClientManager.create({
28
27
  baseUrl: this.apiBaseURL
29
28
  });
30
29
 
31
30
  doReport(event: unknown[]): void {
32
- this.httpClient.post('/report', {
33
- data: event,
34
- timeout: 5000
35
- });
31
+ this.httpClient
32
+ .post('/report', {
33
+ data: event,
34
+ timeout: 5000
35
+ })
36
+ .catch((e) => {
37
+ console.info('report error', e);
38
+ });
36
39
  }
37
40
  }
38
41
 
@@ -5,14 +5,14 @@
5
5
  import { context } from '@/common/context';
6
6
  import { TaskTracker, TaskPoint } from '@/common/report/task-track';
7
7
  import { EventEmitter, logger } from '@jolibox/common';
8
- import JoliboxHttpClient from '../http';
8
+ import { httpClientManager } from '../http';
9
9
  import type { Track } from '.';
10
10
  import type { TrackEvent } from '@jolibox/types';
11
11
 
12
12
  export class H5TaskTracker extends TaskTracker {
13
13
  private gameId: string;
14
14
  private sessionId: string;
15
- private httpClient = new JoliboxHttpClient();
15
+ private httpClient = httpClientManager.create();
16
16
  private track: Track;
17
17
 
18
18
  constructor(track: Track, eventEmitter: EventEmitter<{ visible: [boolean] }>, interval?: number) {
@@ -50,7 +50,10 @@ function addWebviewReadyListener() {
50
50
  }
51
51
 
52
52
  function handleTaskTracker(duration?: number) {
53
- taskTracker.start(duration);
53
+ // 只有小游戏场景需要上报进度
54
+ if (context.mpType === 'game') {
55
+ taskTracker.start(duration);
56
+ }
54
57
  }
55
58
 
56
59
  function addGameServiceReadyListener() {