@whitesev/utils 2.3.0 → 2.3.2

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.
@@ -1,110 +1,110 @@
1
- export declare interface Vue2Object {
2
- $attrs: any;
3
- $children: Vue2Object[];
4
- $createElement: (...args: any[]) => any;
5
- $el: HTMLElement;
6
- $listeners: any;
7
- $options: any;
8
- $parent: Vue2Object;
9
- $refs: any;
10
- $root: Vue2Object;
11
- $scopedSlots: any;
12
- $slots: any;
13
- $store: any;
14
- $vnode: any;
15
- _data: any;
16
- _directInactive: boolean;
17
- _events: any;
18
- _hasHookEvent: boolean;
19
- _isBeingDestroyed: boolean;
20
- _isDestroyed: boolean;
21
- _isMounted: boolean;
22
- _isVue: boolean;
23
- $data: any;
24
- $isServer: boolean;
25
- $props: any;
26
- $route: any & {
27
- fullPath: string;
28
- hash: string;
29
- matched: any[];
30
- meta: any;
31
- name: string;
32
- params: any;
33
- path: string;
34
- query: any;
35
- };
36
- $router: any & {
37
- afterHooks: Function[];
38
- app: Vue2Object;
39
- apps: Vue2Object[];
40
- beforeHooks: Function[];
41
- fallback: boolean;
42
- history: any & {
43
- base: string;
44
- current: any;
45
- listeners: any[];
46
- router: Vue2Object["$router"];
47
- /**
48
- *
49
- * @param delta 访问的距离。如果 delta < 0 则后退相应数量的记录,如果 > 0 则前进。
50
- * @param triggerListeners 是否应该触发连接到该历史的监听器
51
- * @returns
52
- */
53
- go: (delta: number, triggerListeners?: boolean) => void;
54
- /**
55
- *
56
- * @param to 要设置的地址
57
- * @param data 可选的 HistoryState 以关联该导航记录
58
- * @returns
59
- */
60
- push: (to: string, data?: any) => void;
61
- /**
62
- *
63
- * @param to 要设置的地址
64
- * @param data 可选的 HistoryState 以关联该导航记录
65
- * @returns
66
- */
67
- replace: (to: string, data?: any) => void;
68
- };
69
- matcher: any & {
70
- addRoute: (...args: any[]) => any;
71
- addRoutes: (...args: any[]) => any;
72
- getRoutes: () => any;
73
- match: (...args: any[]) => any;
74
- };
75
- mode: string;
76
- resolveHooks: ((...args: any[]) => any)[];
77
- currentRoute: any;
78
- beforeEach: (callback: ((
79
- /** 即将要进入的目标 路由对象 */
80
- to: Vue2Object["$route"],
81
- /** 当前导航正要离开的路由 */
82
- from: Vue2Object["$route"],
83
- /**
84
- *
85
- * + next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
86
- * + next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
87
- * + next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
88
- * + next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
89
- */
90
- next: Function) => void)
91
- /** 移除上一个添加的监听 */
92
- | (() => void)) => void;
93
- afterEach: (callback: ((
94
- /** 即将要进入的目标 路由对象 */
95
- to: Vue2Object["$route"],
96
- /** 当前导航正要离开的路由 */
97
- from: Vue2Object["$route"]) => void)
98
- /** 移除上一个添加的监听 */
99
- | (() => void)) => void;
100
- };
101
- $ssrContext: any;
102
- $watch: (key: string | string[] | (() => any), handler: (this: any, newVal: any, oldVal: any) => void, options?: {
103
- immediate?: boolean;
104
- deep?: boolean;
105
- }) => void;
106
- [key: string]: any;
107
- }
108
- export declare interface HTMLVue2DivElement extends HTMLDivElement {
109
- __vue__: Vue2Object;
110
- }
1
+ export declare interface Vue2Object {
2
+ $attrs: any;
3
+ $children: Vue2Object[];
4
+ $createElement: (...args: any[]) => any;
5
+ $el: HTMLElement;
6
+ $listeners: any;
7
+ $options: any;
8
+ $parent: Vue2Object;
9
+ $refs: any;
10
+ $root: Vue2Object;
11
+ $scopedSlots: any;
12
+ $slots: any;
13
+ $store: any;
14
+ $vnode: any;
15
+ _data: any;
16
+ _directInactive: boolean;
17
+ _events: any;
18
+ _hasHookEvent: boolean;
19
+ _isBeingDestroyed: boolean;
20
+ _isDestroyed: boolean;
21
+ _isMounted: boolean;
22
+ _isVue: boolean;
23
+ $data: any;
24
+ $isServer: boolean;
25
+ $props: any;
26
+ $route: any & {
27
+ fullPath: string;
28
+ hash: string;
29
+ matched: any[];
30
+ meta: any;
31
+ name: string;
32
+ params: any;
33
+ path: string;
34
+ query: any;
35
+ };
36
+ $router: any & {
37
+ afterHooks: Function[];
38
+ app: Vue2Object;
39
+ apps: Vue2Object[];
40
+ beforeHooks: Function[];
41
+ fallback: boolean;
42
+ history: any & {
43
+ base: string;
44
+ current: any;
45
+ listeners: any[];
46
+ router: Vue2Object["$router"];
47
+ /**
48
+ *
49
+ * @param delta 访问的距离。如果 delta < 0 则后退相应数量的记录,如果 > 0 则前进。
50
+ * @param triggerListeners 是否应该触发连接到该历史的监听器
51
+ * @returns
52
+ */
53
+ go: (delta: number, triggerListeners?: boolean) => void;
54
+ /**
55
+ *
56
+ * @param to 要设置的地址
57
+ * @param data 可选的 HistoryState 以关联该导航记录
58
+ * @returns
59
+ */
60
+ push: (to: string, data?: any) => void;
61
+ /**
62
+ *
63
+ * @param to 要设置的地址
64
+ * @param data 可选的 HistoryState 以关联该导航记录
65
+ * @returns
66
+ */
67
+ replace: (to: string, data?: any) => void;
68
+ };
69
+ matcher: any & {
70
+ addRoute: (...args: any[]) => any;
71
+ addRoutes: (...args: any[]) => any;
72
+ getRoutes: () => any;
73
+ match: (...args: any[]) => any;
74
+ };
75
+ mode: string;
76
+ resolveHooks: ((...args: any[]) => any)[];
77
+ currentRoute: any;
78
+ beforeEach: (callback: ((
79
+ /** 即将要进入的目标 路由对象 */
80
+ to: Vue2Object["$route"],
81
+ /** 当前导航正要离开的路由 */
82
+ from: Vue2Object["$route"],
83
+ /**
84
+ *
85
+ * + next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
86
+ * + next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
87
+ * + next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
88
+ * + next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
89
+ */
90
+ next: Function) => void)
91
+ /** 移除上一个添加的监听 */
92
+ | (() => void)) => void;
93
+ afterEach: (callback: ((
94
+ /** 即将要进入的目标 路由对象 */
95
+ to: Vue2Object["$route"],
96
+ /** 当前导航正要离开的路由 */
97
+ from: Vue2Object["$route"]) => void)
98
+ /** 移除上一个添加的监听 */
99
+ | (() => void)) => void;
100
+ };
101
+ $ssrContext: any;
102
+ $watch: (key: string | string[] | (() => any), handler: (this: any, newVal: any, oldVal: any) => void, options?: {
103
+ immediate?: boolean;
104
+ deep?: boolean;
105
+ }) => void;
106
+ [key: string]: any;
107
+ }
108
+ export declare interface HTMLVue2DivElement extends HTMLDivElement {
109
+ __vue__: Vue2Object;
110
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whitesev/utils",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "一个常用的工具库",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
package/src/Httpx.ts CHANGED
@@ -1299,7 +1299,7 @@ class Httpx {
1299
1299
  return uuid;
1300
1300
  } else {
1301
1301
  console.warn(
1302
- "HttpxRequestHook.addBeforeRequestCallBack: fn is not a function"
1302
+ "[Httpx-HttpxRequestHook.addBeforeRequestCallBack] fn is not a function"
1303
1303
  );
1304
1304
  }
1305
1305
  },
@@ -1889,66 +1889,93 @@ class Httpx {
1889
1889
  argumentsList: any
1890
1890
  ) {
1891
1891
  /* X浏览器会因为设置了responseType导致不返回responseText */
1892
- let Response: HttpxAsyncResultData<HttpxDetails> = argumentsList[0];
1892
+ let originResponse: HttpxAsyncResultData<HttpxDetails> = argumentsList[0];
1893
1893
  /* responseText为空,response不为空的情况 */
1894
1894
  if (
1895
- Utils.isNull(Response["responseText"]) &&
1896
- Utils.isNotNull(Response["response"])
1895
+ Utils.isNull(originResponse["responseText"]) &&
1896
+ Utils.isNotNull(originResponse["response"])
1897
1897
  ) {
1898
- if (typeof Response["response"] === "object") {
1898
+ if (typeof originResponse["response"] === "object") {
1899
1899
  Utils.tryCatch().run(() => {
1900
- Response["responseText"] = JSON.stringify(Response["response"]);
1900
+ originResponse["responseText"] = JSON.stringify(
1901
+ originResponse["response"]
1902
+ );
1901
1903
  });
1902
1904
  } else {
1903
- Response["responseText"] = Response["response"];
1905
+ originResponse["responseText"] = originResponse["response"];
1904
1906
  }
1905
1907
  }
1906
1908
 
1907
1909
  /* response为空,responseText不为空的情况 */
1908
1910
  if (
1909
- Response["response"] == null &&
1910
- typeof Response["responseText"] === "string" &&
1911
- Response["responseText"].trim() !== ""
1911
+ originResponse["response"] == null &&
1912
+ typeof originResponse["responseText"] === "string" &&
1913
+ originResponse["responseText"].trim() !== ""
1912
1914
  ) {
1913
- let newResponse = Response["responseText"];
1915
+ /** 原始的请求text */
1916
+ let httpxResponseText = originResponse.responseText;
1917
+ // 自定义个新的response
1918
+ let httpxResponse: any = httpxResponseText;
1914
1919
  if (details.responseType === "json") {
1915
- (newResponse as any) = Utils.toJSON(Response["responseText"]);
1920
+ httpxResponse = Utils.toJSON(httpxResponseText);
1916
1921
  } else if (details.responseType === "document") {
1917
1922
  let parser = new DOMParser();
1918
- (newResponse as any) = parser.parseFromString(
1919
- Response["responseText"],
1923
+ httpxResponse = parser.parseFromString(
1924
+ httpxResponseText,
1920
1925
  "text/html"
1921
1926
  );
1922
1927
  } else if (details.responseType === "arraybuffer") {
1923
1928
  let encoder = new TextEncoder();
1924
- let arrayBuffer = encoder.encode(Response["responseText"]);
1925
- (newResponse as any) = arrayBuffer;
1929
+ let arrayBuffer = encoder.encode(httpxResponseText);
1930
+ httpxResponse = arrayBuffer;
1926
1931
  } else if (details.responseType === "blob") {
1927
1932
  let encoder = new TextEncoder();
1928
- let arrayBuffer = encoder.encode(Response["responseText"]);
1929
- (newResponse as any) = new Blob([arrayBuffer]);
1930
- } else {
1931
- newResponse = Response["responseText"];
1933
+ let arrayBuffer = encoder.encode(httpxResponseText);
1934
+ httpxResponse = new Blob([arrayBuffer]);
1932
1935
  }
1936
+ // 尝试覆盖原response
1933
1937
  try {
1934
- Response["response"] = newResponse;
1938
+ let setStatus = Reflect.set(
1939
+ originResponse,
1940
+ "response",
1941
+ httpxResponse
1942
+ );
1943
+ if (!setStatus) {
1944
+ console.warn(
1945
+ "[Httpx-HttpxCallBack.oonLoad] 覆盖原始 response 失败,尝试添加新的httpxResponse"
1946
+ );
1947
+ try {
1948
+ Reflect.set(originResponse, "httpxResponse", httpxResponse);
1949
+ } catch (error) {
1950
+ console.warn(
1951
+ "[Httpx-HttpxCallBack.oonLoad] httpxResponse 无法被覆盖"
1952
+ );
1953
+ }
1954
+ }
1935
1955
  } catch (error) {
1936
- console.warn("response 无法被覆盖");
1956
+ console.warn(
1957
+ "[Httpx-HttpxCallBack.oonLoad] 原始 response 无法被覆盖,尝试添加新的httpxResponse"
1958
+ );
1959
+ try {
1960
+ Reflect.set(originResponse, "httpxResponse", httpxResponse);
1961
+ } catch (error) {
1962
+ console.warn(
1963
+ "[Httpx-HttpxCallBack.oonLoad] httpxResponse 无法被覆盖"
1964
+ );
1965
+ }
1937
1966
  }
1938
1967
  }
1939
1968
  /* Stay扩展中没有finalUrl,对应的是responseURL */
1940
- if (
1941
- Response["finalUrl"] == null &&
1942
- (Response as any)["responseURL"] != null
1943
- ) {
1944
- Response["finalUrl"] = (Response as any)["responseURL"];
1969
+ let originResponseURL = Reflect.get(originResponse, "responseURL");
1970
+ if (originResponse["finalUrl"] == null && originResponseURL != null) {
1971
+ Reflect.set(originResponse, "finalUrl", originResponseURL);
1945
1972
  }
1946
1973
 
1947
1974
  /* 状态码2xx都是成功的 */
1948
- if (Math.floor(Response.status / 100) === 2) {
1975
+ if (Math.floor(originResponse.status / 100) === 2) {
1949
1976
  if (
1950
1977
  this.context.HttpxResponseHook.successResponseCallBack(
1951
- Response,
1978
+ originResponse,
1952
1979
  details
1953
1980
  ) == null
1954
1981
  ) {
@@ -1957,7 +1984,7 @@ class Httpx {
1957
1984
  }
1958
1985
  resolve({
1959
1986
  status: true,
1960
- data: Response,
1987
+ data: originResponse,
1961
1988
  details: details,
1962
1989
  msg: "请求完毕",
1963
1990
  type: "onload",
@@ -2007,7 +2034,7 @@ class Httpx {
2007
2034
  */
2008
2035
  request(details: Required<HttpxDetails>) {
2009
2036
  if (this.context.#LOG_DETAILS) {
2010
- console.log("Httpx请求配置👇", details);
2037
+ console.log("[Httpx-HttpxRequest.request] 请求前的配置👇", details);
2011
2038
  }
2012
2039
  if (
2013
2040
  typeof this.context.HttpxRequestHook.beforeRequestCallBack ===
@@ -2047,37 +2074,43 @@ class Httpx {
2047
2074
  abortController: AbortController
2048
2075
  ) {
2049
2076
  fetch(details.url, fetchRequestInit)
2050
- .then(async (resp) => {
2051
- /**
2052
- * @type {HttpxAsyncResultData}
2053
- */
2054
- let httpxResponse = {
2077
+ .then(async (fetchResponse) => {
2078
+ /** 自定义的response */
2079
+ let httpxResponse: HttpxAsyncResultData = {
2055
2080
  isFetch: true,
2056
- finalUrl: resp.url,
2081
+ finalUrl: fetchResponse.url,
2057
2082
  readyState: 4,
2058
- status: resp.status,
2059
- statusText: resp.statusText,
2083
+ // @ts-ignore
2084
+ status: fetchResponse.status,
2085
+ statusText: fetchResponse.statusText,
2060
2086
  response: void 0,
2061
- responseFetchHeaders: resp.headers,
2087
+ responseFetchHeaders: fetchResponse.headers,
2062
2088
  responseHeaders: "",
2089
+ // @ts-ignore
2063
2090
  responseText: void 0,
2064
2091
  responseType: details.responseType,
2065
2092
  responseXML: void 0,
2066
2093
  };
2067
2094
  Object.assign(httpxResponse, details.context || {});
2068
2095
 
2069
- for (const [key, value] of (resp.headers as any).entries()) {
2096
+ // headers转为字符串
2097
+ for (const [key, value] of (fetchResponse.headers as any).entries()) {
2070
2098
  httpxResponse.responseHeaders += `${key}: ${value}\n`;
2071
2099
  }
2072
2100
 
2073
- /* 如果是流式传输,直接返回 */
2101
+ /** 请求返回的类型 */
2102
+ const fetchResponseType = fetchResponse.headers.get("Content-Type");
2103
+
2104
+ /* 如果需要stream,且获取到的是stream,那直接返回 */
2074
2105
  if (
2075
2106
  details.responseType === "stream" ||
2076
- (resp.headers.has("Content-Type") &&
2077
- resp.headers.get("Content-Type")!.includes("text/event-stream"))
2107
+ (fetchResponse.headers.has("Content-Type") &&
2108
+ fetchResponse.headers
2109
+ .get("Content-Type")!
2110
+ .includes("text/event-stream"))
2078
2111
  ) {
2079
- (httpxResponse as any)["isStream"] = true;
2080
- (httpxResponse as any).response = resp.body;
2112
+ Reflect.set(httpxResponse, "isStream", true);
2113
+ Reflect.set(httpxResponse, "response", fetchResponse.body);
2081
2114
  Reflect.deleteProperty(httpxResponse, "responseText");
2082
2115
  Reflect.deleteProperty(httpxResponse, "responseXML");
2083
2116
  details.onload(httpxResponse);
@@ -2085,57 +2118,67 @@ class Httpx {
2085
2118
  }
2086
2119
 
2087
2120
  /** 响应 */
2088
- let response = "";
2121
+ let response: any = "";
2089
2122
  /** 响应字符串 */
2090
2123
  let responseText = "";
2091
2124
  /** 响应xml文档 */
2092
- let responseXML = "";
2093
-
2094
- let arrayBuffer = await resp.arrayBuffer();
2125
+ let responseXML: XMLDocument | string = "";
2126
+ /** 先获取二进制数据 */
2127
+ let arrayBuffer = await fetchResponse.arrayBuffer();
2095
2128
 
2129
+ /** 数据编码 */
2096
2130
  let encoding = "utf-8";
2097
- if (resp.headers.has("Content-Type")) {
2098
- let charsetMatched = resp.headers
2131
+ if (fetchResponse.headers.has("Content-Type")) {
2132
+ let charsetMatched = fetchResponse.headers
2099
2133
  .get("Content-Type")
2100
2134
  ?.match(/charset=(.+)/);
2101
2135
  if (charsetMatched) {
2102
2136
  encoding = charsetMatched[1];
2137
+ encoding = encoding.toLowerCase();
2103
2138
  }
2104
2139
  }
2140
+ // Failed to construct 'TextDecoder': The encoding label provided ('"UTF-8"') is invalid.
2141
+ // 去除引号
2142
+ encoding = encoding.replace(/('|")/gi, "");
2143
+ // 编码
2105
2144
  let textDecoder = new TextDecoder(encoding);
2106
2145
  responseText = textDecoder.decode(arrayBuffer);
2107
2146
  response = responseText;
2108
2147
 
2109
2148
  if (details.responseType === "arraybuffer") {
2110
- (response as any) = arrayBuffer;
2149
+ // response返回格式是二进制流
2150
+ response = arrayBuffer;
2111
2151
  } else if (details.responseType === "blob") {
2112
- (response as any) = new Blob([arrayBuffer as any]);
2152
+ // response返回格式是blob
2153
+ response = new Blob([arrayBuffer]);
2154
+ } else if (
2155
+ details.responseType === "json" ||
2156
+ (typeof fetchResponseType === "string" &&
2157
+ fetchResponseType.includes("application/json"))
2158
+ ) {
2159
+ // response返回格式是JSON格式
2160
+ response = Utils.toJSON(responseText);
2113
2161
  } else if (
2114
2162
  details.responseType === "document" ||
2115
2163
  details.responseType == null
2116
2164
  ) {
2165
+ // response返回格式是文档格式
2117
2166
  let parser = new DOMParser();
2118
- (response as any) = parser.parseFromString(
2119
- responseText,
2120
- "text/html"
2121
- );
2122
- } else if (details.responseType === "json") {
2123
- (response as any) = Utils.toJSON(responseText);
2167
+ response = parser.parseFromString(responseText, "text/html");
2124
2168
  }
2169
+ // 转为XML结构
2125
2170
  let parser = new DOMParser();
2126
- (responseXML as any) = parser.parseFromString(
2127
- responseText,
2128
- "text/xml"
2129
- );
2171
+ responseXML = parser.parseFromString(responseText, "text/xml");
2130
2172
 
2131
- (httpxResponse as any).response = response;
2132
- (httpxResponse as any).responseText = responseText;
2133
- (httpxResponse as any).responseXML = responseXML;
2173
+ Reflect.set(httpxResponse, "response", response);
2174
+ Reflect.set(httpxResponse, "responseText", responseText);
2175
+ Reflect.set(httpxResponse, "responseXML", responseXML);
2134
2176
 
2177
+ // 执行回调
2135
2178
  details.onload(httpxResponse);
2136
2179
  })
2137
- .catch((err) => {
2138
- if (err.name === "AbortError") {
2180
+ .catch((error: any) => {
2181
+ if (error.name === "AbortError") {
2139
2182
  return;
2140
2183
  }
2141
2184
  details.onerror({
@@ -2146,7 +2189,7 @@ class Httpx {
2146
2189
  statusText: "",
2147
2190
  responseHeaders: "",
2148
2191
  responseText: "",
2149
- error: err,
2192
+ error: error,
2150
2193
  });
2151
2194
  });
2152
2195
  details.onloadstart({
@@ -2210,7 +2253,7 @@ class Httpx {
2210
2253
  constructor(__xmlHttpRequest__?: any) {
2211
2254
  if (typeof __xmlHttpRequest__ !== "function") {
2212
2255
  console.warn(
2213
- "Httpx未传入GM_xmlhttpRequest函数或传入的GM_xmlhttpRequest不是Function,强制使用window.fetch"
2256
+ "[Httpx-constructor] 未传入GM_xmlhttpRequest函数或传入的GM_xmlhttpRequest不是Function,将默认使用window.fetch"
2214
2257
  );
2215
2258
  }
2216
2259
  this.interceptors.request.context = this as any;
package/src/Utils.ts CHANGED
@@ -3951,20 +3951,48 @@ class Utils {
3951
3951
  compareArrayData?: TT[],
3952
3952
  compareFun?: (item1: T, item2: TT) => boolean
3953
3953
  ): any[];
3954
- uniqueArray<T extends any, TT extends any>(
3954
+ /**
3955
+ * 数组去重,去除不需要的值
3956
+ * @param uniqueArrayData 需要过滤的数组
3957
+ * @param getIdentfierValue 获取用于确定唯一性的值
3958
+ * @example
3959
+ * Utils.uniqueArray([{name:"1",host:"baidu.com"},{name:"2",host:"baidu.com"},{name:"3",host:"baidu.com"}]);
3960
+ * > [{name:"1",host:"baidu.com"}]
3961
+ */
3962
+ uniqueArray<T>(
3963
+ uniqueArrayData: T[],
3964
+ getIdentfierValue: (itemValue: T) => any
3965
+ ): T[];
3966
+ uniqueArray<T, T2>(
3955
3967
  uniqueArrayData: T[] = [],
3956
- compareArrayData: TT[] = [],
3957
- compareFun: (item1: T, item2: TT) => boolean = (item, item2) => {
3958
- // @ts-ignore
3968
+ compareArrayData: any,
3969
+ compareFun: any = (item: any, item2: any) => {
3959
3970
  return item === item2;
3960
3971
  }
3961
3972
  ): any[] {
3962
- return Array.from(uniqueArrayData).filter(
3963
- (item) =>
3964
- !Array.from(compareArrayData).some(function (item2) {
3965
- return compareFun(item, item2);
3966
- })
3967
- );
3973
+ if (typeof compareArrayData === "function") {
3974
+ const compareFn = compareArrayData;
3975
+ const seen = new Set();
3976
+
3977
+ const result: T[] = [];
3978
+ for (const item of uniqueArrayData) {
3979
+ // 使用compareFn函数来获取当前对象的唯一标识
3980
+ const identfier = compareFn(item);
3981
+ // 如果Set中还没有这个标识,则添加到结果数组中,并将其标识存入Set
3982
+ if (!seen.has(identfier)) {
3983
+ seen.add(identfier);
3984
+ result.push(item);
3985
+ }
3986
+ }
3987
+ return result;
3988
+ } else {
3989
+ return Array.from(uniqueArrayData).filter(
3990
+ (item) =>
3991
+ !Array.from(compareArrayData).some(function (item2) {
3992
+ return compareFun(item, item2);
3993
+ })
3994
+ );
3995
+ }
3968
3996
  }
3969
3997
  /**
3970
3998
  * 等待函数数组全部执行完毕,注意,每个函数的顺序不是同步