@tarojs/plugin-http 3.7.0-alpha.2 → 3.7.0-alpha.22
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.
- package/dist/index.js +15 -0
- package/dist/runtime.d.ts +19 -10
- package/dist/runtime.js +94 -25
- package/package.json +5 -5
- package/src/index.ts +17 -1
- package/src/runtime/XMLHttpRequest.ts +95 -25
- package/src/runtime/index.ts +8 -2
package/dist/index.js
CHANGED
|
@@ -26,6 +26,21 @@ var index = (ctx, options) => {
|
|
|
26
26
|
((_b = options.disabledBlob) !== null && _b !== void 0 ? _b : true) && ((_d = args[0]).Blob || (_d.Blob = [runtimeAlias, 'Blob']));
|
|
27
27
|
return args;
|
|
28
28
|
});
|
|
29
|
+
if (ctx.initialConfig.compiler === 'webpack4' || (shared.isObject(ctx.initialConfig.compiler) && ctx.initialConfig.compiler.type === 'webpack4')) {
|
|
30
|
+
// taro webpack4 中, 未正确识别到 axios package.json 中的 browser 字段, 以致于打包进入了 node 相关的代码(https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/package.json#L128-L132)
|
|
31
|
+
const inAxiosReg = /(\/|\\)(node_modules)(\/|\\)(axios)(\/|\\)/;
|
|
32
|
+
chain.merge({
|
|
33
|
+
externals: [
|
|
34
|
+
(context, request, callback) => {
|
|
35
|
+
if (inAxiosReg.test(context) && request.includes('http.js')) {
|
|
36
|
+
// 将 http 适配器从源码里干掉 https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/lib/adapters/adapters.js#L2
|
|
37
|
+
return callback(null, 'var undefined');
|
|
38
|
+
}
|
|
39
|
+
callback();
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
29
44
|
}
|
|
30
45
|
});
|
|
31
46
|
ctx.registerMethod({
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { document, Events } from '@tarojs/runtime';
|
|
1
|
+
import { document, Events, TaroEvent } from '@tarojs/runtime';
|
|
2
2
|
declare class Cookie {
|
|
3
3
|
#private;
|
|
4
4
|
constructor();
|
|
@@ -41,6 +41,12 @@ declare class Cookie {
|
|
|
41
41
|
*/
|
|
42
42
|
deserialize(str: any): void;
|
|
43
43
|
}
|
|
44
|
+
interface XMLHttpRequestEvent extends TaroEvent {
|
|
45
|
+
target: XMLHttpRequest;
|
|
46
|
+
currentTarget: XMLHttpRequest;
|
|
47
|
+
loaded: number;
|
|
48
|
+
total: number;
|
|
49
|
+
}
|
|
44
50
|
// https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
|
|
45
51
|
declare class XMLHttpRequest extends Events {
|
|
46
52
|
#private;
|
|
@@ -52,21 +58,24 @@ declare class XMLHttpRequest extends Events {
|
|
|
52
58
|
// 欺骗一些库让其认为是原生的xhr
|
|
53
59
|
static toString(): string;
|
|
54
60
|
toString(): string;
|
|
55
|
-
//
|
|
61
|
+
// 事件正常流转: loadstart => progress(可能多次) => load => loadend
|
|
62
|
+
// error 流转: loadstart => error => loadend
|
|
63
|
+
// abort 流转: loadstart => abort => loadend
|
|
64
|
+
// web在线测试: https://developer.mozilla.org/zh-CN/play
|
|
56
65
|
/** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
|
|
57
|
-
onabort: (() => void) | null;
|
|
66
|
+
onabort: ((e: XMLHttpRequestEvent) => void) | null;
|
|
58
67
|
/** 当 request 遭遇错误时触发 */
|
|
59
|
-
onerror: ((
|
|
68
|
+
onerror: ((e: XMLHttpRequestEvent) => void) | null;
|
|
60
69
|
/** 接收到响应数据时触发 */
|
|
61
|
-
onloadstart: (() => void) | null;
|
|
70
|
+
onloadstart: ((e: XMLHttpRequestEvent) => void) | null;
|
|
62
71
|
/** 请求成功完成时触发 */
|
|
63
|
-
onload: (() => void) | null;
|
|
72
|
+
onload: ((e: XMLHttpRequestEvent) => void) | null;
|
|
64
73
|
/** 当请求结束时触发,无论请求成功 ( load) 还是失败 (abort 或 error)。 */
|
|
65
|
-
onloadend: (() => void) | null;
|
|
74
|
+
onloadend: ((e: XMLHttpRequestEvent) => void) | null;
|
|
66
75
|
/** 在预设时间内没有接收到响应时触发 */
|
|
67
|
-
ontimeout: (() => void) | null;
|
|
76
|
+
ontimeout: ((e: XMLHttpRequestEvent) => void) | null;
|
|
68
77
|
/** 当 readyState 属性发生变化时,调用的事件处理器 */
|
|
69
|
-
onreadystatechange: (() => void) | null;
|
|
78
|
+
onreadystatechange: ((e: XMLHttpRequestEvent) => void) | null;
|
|
70
79
|
constructor();
|
|
71
80
|
addEventListener(event: string, callback: (arg: any) => void): void;
|
|
72
81
|
removeEventListener(event: string, callback: (arg: any) => void): void;
|
|
@@ -91,4 +100,4 @@ declare class XMLHttpRequest extends Events {
|
|
|
91
100
|
setRequestHeader(header: any, value: any): void;
|
|
92
101
|
send(data: any): void;
|
|
93
102
|
}
|
|
94
|
-
export { Cookie, document, XMLHttpRequest };
|
|
103
|
+
export { Cookie, document, XMLHttpRequest, XMLHttpRequestEvent };
|
package/dist/runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseUrl, Events, window, document } from '@tarojs/runtime';
|
|
1
|
+
import { parseUrl, Events, createEvent, window, document } from '@tarojs/runtime';
|
|
2
2
|
export { document } from '@tarojs/runtime';
|
|
3
3
|
import { isString, isFunction, isWebPlatform } from '@tarojs/shared';
|
|
4
4
|
import { setStorage, getStorageSync, request } from '@tarojs/taro';
|
|
@@ -17,6 +17,8 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
17
17
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
18
18
|
PERFORMANCE OF THIS SOFTWARE.
|
|
19
19
|
***************************************************************************** */
|
|
20
|
+
/* global Reflect, Promise */
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
22
24
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
@@ -351,8 +353,43 @@ const STATUS_TEXT_MAP = {
|
|
|
351
353
|
504: 'Gateway Timeout',
|
|
352
354
|
505: 'HTTP Version Not Supported',
|
|
353
355
|
};
|
|
356
|
+
function createXMLHttpRequestEvent(event, target, loaded) {
|
|
357
|
+
const e = createEvent(event);
|
|
358
|
+
try {
|
|
359
|
+
Object.defineProperties(e, {
|
|
360
|
+
'currentTarget': {
|
|
361
|
+
enumerable: true,
|
|
362
|
+
value: target
|
|
363
|
+
},
|
|
364
|
+
'target': {
|
|
365
|
+
enumerable: true,
|
|
366
|
+
value: target
|
|
367
|
+
},
|
|
368
|
+
'loaded': {
|
|
369
|
+
enumerable: true,
|
|
370
|
+
value: loaded || 0
|
|
371
|
+
},
|
|
372
|
+
// 读 Content-Range 字段,目前来说作用不大,先和 loaded 保持一致
|
|
373
|
+
'total': {
|
|
374
|
+
enumerable: true,
|
|
375
|
+
value: loaded || 0
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
catch (err) {
|
|
380
|
+
// no handler
|
|
381
|
+
}
|
|
382
|
+
return e;
|
|
383
|
+
}
|
|
354
384
|
// https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
|
|
355
385
|
class XMLHttpRequest extends Events {
|
|
386
|
+
// 欺骗一些库让其认为是原生的xhr
|
|
387
|
+
static toString() {
|
|
388
|
+
return 'function XMLHttpRequest() { [native code] }';
|
|
389
|
+
}
|
|
390
|
+
toString() {
|
|
391
|
+
return '[object XMLHttpRequest]';
|
|
392
|
+
}
|
|
356
393
|
constructor() {
|
|
357
394
|
super();
|
|
358
395
|
_XMLHttpRequest_instances.add(this);
|
|
@@ -369,7 +406,10 @@ class XMLHttpRequest extends Events {
|
|
|
369
406
|
_XMLHttpRequest_timeout.set(this, void 0);
|
|
370
407
|
_XMLHttpRequest_withCredentials.set(this, void 0);
|
|
371
408
|
_XMLHttpRequest_requestTask.set(this, void 0);
|
|
372
|
-
//
|
|
409
|
+
// 事件正常流转: loadstart => progress(可能多次) => load => loadend
|
|
410
|
+
// error 流转: loadstart => error => loadend
|
|
411
|
+
// abort 流转: loadstart => abort => loadend
|
|
412
|
+
// web在线测试: https://developer.mozilla.org/zh-CN/play
|
|
373
413
|
/** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
|
|
374
414
|
this.onabort = null;
|
|
375
415
|
/** 当 request 遭遇错误时触发 */
|
|
@@ -401,13 +441,6 @@ class XMLHttpRequest extends Events {
|
|
|
401
441
|
__classPrivateFieldSet(this, _XMLHttpRequest_withCredentials, true, "f");
|
|
402
442
|
__classPrivateFieldSet(this, _XMLHttpRequest_requestTask, null, "f");
|
|
403
443
|
}
|
|
404
|
-
// 欺骗一些库让其认为是原生的xhr
|
|
405
|
-
static toString() {
|
|
406
|
-
return 'function XMLHttpRequest() { [native code] }';
|
|
407
|
-
}
|
|
408
|
-
toString() {
|
|
409
|
-
return '[object XMLHttpRequest]';
|
|
410
|
-
}
|
|
411
444
|
addEventListener(event, callback) {
|
|
412
445
|
if (!isString(event))
|
|
413
446
|
return;
|
|
@@ -466,8 +499,9 @@ class XMLHttpRequest extends Events {
|
|
|
466
499
|
abort() {
|
|
467
500
|
if (__classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f")) {
|
|
468
501
|
__classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f").abort();
|
|
469
|
-
|
|
470
|
-
|
|
502
|
+
const abortEvent = createXMLHttpRequestEvent('abort', this, 0);
|
|
503
|
+
this.trigger('abort', abortEvent);
|
|
504
|
+
isFunction(this.onabort) && this.onabort(abortEvent);
|
|
471
505
|
}
|
|
472
506
|
}
|
|
473
507
|
getAllResponseHeaders() {
|
|
@@ -512,8 +546,9 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
512
546
|
const hasChange = readyState !== __classPrivateFieldGet(this, _XMLHttpRequest_readyState, "f");
|
|
513
547
|
__classPrivateFieldSet(this, _XMLHttpRequest_readyState, readyState, "f");
|
|
514
548
|
if (hasChange) {
|
|
515
|
-
|
|
516
|
-
|
|
549
|
+
const readystatechangeEvent = createXMLHttpRequestEvent('readystatechange', this, 0);
|
|
550
|
+
this.trigger('readystatechange', readystatechangeEvent);
|
|
551
|
+
isFunction(this.onreadystatechange) && this.onreadystatechange(readystatechangeEvent);
|
|
517
552
|
}
|
|
518
553
|
}, _XMLHttpRequest_callRequest = function _XMLHttpRequest_callRequest() {
|
|
519
554
|
if (!window || !window.document) {
|
|
@@ -527,8 +562,9 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
527
562
|
if (__classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f"))
|
|
528
563
|
__classPrivateFieldGet(this, _XMLHttpRequest_requestTask, "f").abort();
|
|
529
564
|
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.DONE);
|
|
530
|
-
|
|
531
|
-
|
|
565
|
+
const timeoutEvent = createXMLHttpRequestEvent('timeout', this, 0);
|
|
566
|
+
this.trigger('timeout', timeoutEvent);
|
|
567
|
+
isFunction(this.ontimeout) && this.ontimeout(timeoutEvent);
|
|
532
568
|
}
|
|
533
569
|
}, __classPrivateFieldGet(this, _XMLHttpRequest_timeout, "f"));
|
|
534
570
|
}
|
|
@@ -543,7 +579,8 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
543
579
|
url = url.indexOf('//') === -1 ? window.location.origin + url : url;
|
|
544
580
|
// 头信息
|
|
545
581
|
const header = Object.assign({}, __classPrivateFieldGet(this, _XMLHttpRequest_header, "f"));
|
|
546
|
-
|
|
582
|
+
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
|
|
583
|
+
header.cookie = window.document.$$cookie;
|
|
547
584
|
if (!this.withCredentials) {
|
|
548
585
|
// 不同源,要求 withCredentials 为 true 才携带 cookie
|
|
549
586
|
const { origin } = parseUrl(url);
|
|
@@ -600,23 +637,49 @@ _XMLHttpRequest_method = new WeakMap(), _XMLHttpRequest_url = new WeakMap(), _XM
|
|
|
600
637
|
// 处理返回数据
|
|
601
638
|
if (data) {
|
|
602
639
|
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.LOADING);
|
|
603
|
-
|
|
604
|
-
|
|
640
|
+
const loadstartEvent = createXMLHttpRequestEvent('loadstart', this, header['Content-Length']);
|
|
641
|
+
this.trigger('loadstart', loadstartEvent);
|
|
642
|
+
isFunction(this.onloadstart) && this.onloadstart(loadstartEvent);
|
|
605
643
|
__classPrivateFieldSet(this, _XMLHttpRequest_response, data, "f");
|
|
606
|
-
|
|
607
|
-
|
|
644
|
+
const loadEvent = createXMLHttpRequestEvent('load', this, header['Content-Length']);
|
|
645
|
+
this.trigger('load', loadEvent);
|
|
646
|
+
isFunction(this.onload) && this.onload(loadEvent);
|
|
608
647
|
}
|
|
609
648
|
}, _XMLHttpRequest_requestFail = function _XMLHttpRequest_requestFail(err) {
|
|
649
|
+
// 微信小程序,无论接口返回200还是其他,响应无论是否有错误,都会进入 success 回调;只有类似超时这种请求错误才会进入 fail 回调
|
|
650
|
+
//
|
|
651
|
+
/**
|
|
652
|
+
* 阿里系小程序,接口返回非200状态码,会进入 fail 回调, 此时 err 对象结构如下(当错误码为 14 或 19 时,会多返回 status、data、headers。可通过这些字段获取服务端相关错误信息):
|
|
653
|
+
{
|
|
654
|
+
data: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
655
|
+
error: 19
|
|
656
|
+
errorMessage: "http status error"
|
|
657
|
+
headers: {date: 'Mon, 14 Aug 2023 08:54:58 GMT', content-type: 'application/json;charset=UTF-8', content-length: '52', connection: 'close', access-control-allow-credentials: 'true', …}
|
|
658
|
+
originalData: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
659
|
+
status: 401
|
|
660
|
+
}
|
|
661
|
+
*/
|
|
662
|
+
// 统一行为,能正常响应的,都算 success.
|
|
663
|
+
if (err.status) {
|
|
664
|
+
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_requestSuccess).call(this, {
|
|
665
|
+
data: err,
|
|
666
|
+
statusCode: err.status,
|
|
667
|
+
header: err.headers
|
|
668
|
+
});
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
610
671
|
__classPrivateFieldSet(this, _XMLHttpRequest_status, 0, "f");
|
|
611
|
-
__classPrivateFieldSet(this, _XMLHttpRequest_statusText, err.errMsg, "f");
|
|
612
|
-
|
|
613
|
-
|
|
672
|
+
__classPrivateFieldSet(this, _XMLHttpRequest_statusText, err.errMsg || err.errorMessage, "f");
|
|
673
|
+
const errorEvent = createXMLHttpRequestEvent('error', this, 0);
|
|
674
|
+
this.trigger('error', errorEvent);
|
|
675
|
+
isFunction(this.onerror) && this.onerror(errorEvent);
|
|
614
676
|
}, _XMLHttpRequest_requestComplete = function _XMLHttpRequest_requestComplete() {
|
|
615
677
|
__classPrivateFieldSet(this, _XMLHttpRequest_requestTask, null, "f");
|
|
616
678
|
__classPrivateFieldGet(this, _XMLHttpRequest_instances, "m", _XMLHttpRequest_callReadyStateChange).call(this, XMLHttpRequest.DONE);
|
|
617
679
|
if (__classPrivateFieldGet(this, _XMLHttpRequest_status, "f")) {
|
|
618
|
-
|
|
619
|
-
|
|
680
|
+
const loadendEvent = createXMLHttpRequestEvent('loadend', this, __classPrivateFieldGet(this, _XMLHttpRequest_header, "f")['Content-Length']);
|
|
681
|
+
this.trigger('loadend', loadendEvent);
|
|
682
|
+
isFunction(this.onloadend) && this.onloadend(loadendEvent);
|
|
620
683
|
}
|
|
621
684
|
};
|
|
622
685
|
XMLHttpRequest.UNSENT = 0;
|
|
@@ -646,6 +709,12 @@ if (!isWebPlatform()) {
|
|
|
646
709
|
_cookie.setCookie(value, this.URL);
|
|
647
710
|
},
|
|
648
711
|
},
|
|
712
|
+
/** 获取完整的 cookie,包括 httpOnly 也能获取到 */
|
|
713
|
+
$$cookie: {
|
|
714
|
+
get() {
|
|
715
|
+
return _cookie.getCookie(this.URL, true);
|
|
716
|
+
},
|
|
717
|
+
}
|
|
649
718
|
});
|
|
650
719
|
}
|
|
651
720
|
window.XMLHttpRequest = XMLHttpRequest;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tarojs/plugin-http",
|
|
3
|
-
"version": "3.7.0-alpha.
|
|
3
|
+
"version": "3.7.0-alpha.22",
|
|
4
4
|
"description": "Taro 小程序端支持使用 web 请求 的插件",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://github.com/NervJS/taro#readme",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@tarojs/runtime": "3.7.0-alpha.
|
|
27
|
-
"@tarojs/service": "3.7.0-alpha.
|
|
28
|
-
"@tarojs/shared": "3.7.0-alpha.
|
|
26
|
+
"@tarojs/runtime": "3.7.0-alpha.22",
|
|
27
|
+
"@tarojs/service": "3.7.0-alpha.22",
|
|
28
|
+
"@tarojs/shared": "3.7.0-alpha.22"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@rollup/plugin-json": "^
|
|
31
|
+
"@rollup/plugin-json": "^6.0.0",
|
|
32
32
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
33
33
|
"jest": "^29.3.1",
|
|
34
34
|
"jest-cli": "^29.3.1",
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isArray, isString } from '@tarojs/shared'
|
|
1
|
+
import { isArray, isObject, isString } from '@tarojs/shared'
|
|
2
2
|
import path from 'path'
|
|
3
3
|
|
|
4
4
|
import { name as packageName } from '../package.json'
|
|
@@ -35,6 +35,22 @@ export default (ctx: IPluginContext, options: IOptions) => {
|
|
|
35
35
|
|
|
36
36
|
return args
|
|
37
37
|
})
|
|
38
|
+
|
|
39
|
+
if (ctx.initialConfig.compiler === 'webpack4' || (isObject<boolean>(ctx.initialConfig.compiler) && ctx.initialConfig.compiler.type === 'webpack4')) {
|
|
40
|
+
// taro webpack4 中, 未正确识别到 axios package.json 中的 browser 字段, 以致于打包进入了 node 相关的代码(https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/package.json#L128-L132)
|
|
41
|
+
const inAxiosReg = /(\/|\\)(node_modules)(\/|\\)(axios)(\/|\\)/
|
|
42
|
+
chain.merge({
|
|
43
|
+
externals: [
|
|
44
|
+
(context, request, callback) => {
|
|
45
|
+
if (inAxiosReg.test(context) && request.includes('http.js')) {
|
|
46
|
+
// 将 http 适配器从源码里干掉 https://github.com/axios/axios/blob/59eb99183546d822bc27e881f5dcd748daa04173/lib/adapters/adapters.js#L2
|
|
47
|
+
return callback(null, 'var undefined')
|
|
48
|
+
}
|
|
49
|
+
callback()
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
})
|
|
53
|
+
}
|
|
38
54
|
}
|
|
39
55
|
})
|
|
40
56
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Events, parseUrl, window } from '@tarojs/runtime'
|
|
1
|
+
import { createEvent, Events, parseUrl, TaroEvent, window } from '@tarojs/runtime'
|
|
2
2
|
import { isFunction, isString } from '@tarojs/shared'
|
|
3
3
|
import { request } from '@tarojs/taro'
|
|
4
4
|
|
|
@@ -51,6 +51,42 @@ const STATUS_TEXT_MAP = {
|
|
|
51
51
|
504: 'Gateway Timeout',
|
|
52
52
|
505: 'HTTP Version Not Supported',
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
export interface XMLHttpRequestEvent extends TaroEvent {
|
|
56
|
+
target: XMLHttpRequest
|
|
57
|
+
currentTarget: XMLHttpRequest
|
|
58
|
+
loaded: number
|
|
59
|
+
total: number
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function createXMLHttpRequestEvent (event: string, target:XMLHttpRequest, loaded: number): XMLHttpRequestEvent {
|
|
63
|
+
const e = createEvent(event) as XMLHttpRequestEvent
|
|
64
|
+
try {
|
|
65
|
+
Object.defineProperties(e, {
|
|
66
|
+
'currentTarget': {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
value: target
|
|
69
|
+
},
|
|
70
|
+
'target': {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
value: target
|
|
73
|
+
},
|
|
74
|
+
'loaded': {
|
|
75
|
+
enumerable: true,
|
|
76
|
+
value: loaded || 0
|
|
77
|
+
},
|
|
78
|
+
// 读 Content-Range 字段,目前来说作用不大,先和 loaded 保持一致
|
|
79
|
+
'total': {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
value: loaded || 0
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
} catch (err) {
|
|
85
|
+
// no handler
|
|
86
|
+
}
|
|
87
|
+
return e
|
|
88
|
+
}
|
|
89
|
+
|
|
54
90
|
// https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
|
|
55
91
|
export class XMLHttpRequest extends Events {
|
|
56
92
|
static readonly UNSENT = 0
|
|
@@ -82,28 +118,31 @@ export class XMLHttpRequest extends Events {
|
|
|
82
118
|
#withCredentials: boolean
|
|
83
119
|
#requestTask: null | Taro.RequestTask<any>
|
|
84
120
|
|
|
85
|
-
//
|
|
121
|
+
// 事件正常流转: loadstart => progress(可能多次) => load => loadend
|
|
122
|
+
// error 流转: loadstart => error => loadend
|
|
123
|
+
// abort 流转: loadstart => abort => loadend
|
|
124
|
+
// web在线测试: https://developer.mozilla.org/zh-CN/play
|
|
86
125
|
|
|
87
126
|
/** 当 request 被停止时触发,例如当程序调用 XMLHttpRequest.abort() 时 */
|
|
88
|
-
onabort: (() => void) | null = null
|
|
127
|
+
onabort: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
89
128
|
|
|
90
129
|
/** 当 request 遭遇错误时触发 */
|
|
91
|
-
onerror: ((
|
|
130
|
+
onerror: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
92
131
|
|
|
93
132
|
/** 接收到响应数据时触发 */
|
|
94
|
-
onloadstart: (() => void) | null = null
|
|
133
|
+
onloadstart: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
95
134
|
|
|
96
135
|
/** 请求成功完成时触发 */
|
|
97
|
-
onload: (() => void) | null = null
|
|
136
|
+
onload: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
98
137
|
|
|
99
138
|
/** 当请求结束时触发,无论请求成功 ( load) 还是失败 (abort 或 error)。 */
|
|
100
|
-
onloadend: (() => void) | null = null
|
|
139
|
+
onloadend: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
101
140
|
|
|
102
141
|
/** 在预设时间内没有接收到响应时触发 */
|
|
103
|
-
ontimeout: (() => void) | null = null
|
|
142
|
+
ontimeout: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
104
143
|
|
|
105
144
|
/** 当 readyState 属性发生变化时,调用的事件处理器 */
|
|
106
|
-
onreadystatechange: (() => void) | null = null
|
|
145
|
+
onreadystatechange: ((e: XMLHttpRequestEvent) => void) | null = null
|
|
107
146
|
|
|
108
147
|
constructor () {
|
|
109
148
|
super()
|
|
@@ -145,8 +184,9 @@ export class XMLHttpRequest extends Events {
|
|
|
145
184
|
this.#readyState = readyState
|
|
146
185
|
|
|
147
186
|
if (hasChange) {
|
|
148
|
-
|
|
149
|
-
|
|
187
|
+
const readystatechangeEvent = createXMLHttpRequestEvent('readystatechange', this, 0)
|
|
188
|
+
this.trigger('readystatechange', readystatechangeEvent)
|
|
189
|
+
isFunction(this.onreadystatechange) && this.onreadystatechange(readystatechangeEvent)
|
|
150
190
|
}
|
|
151
191
|
}
|
|
152
192
|
|
|
@@ -165,8 +205,9 @@ export class XMLHttpRequest extends Events {
|
|
|
165
205
|
// 超时
|
|
166
206
|
if (this.#requestTask) this.#requestTask.abort()
|
|
167
207
|
this.#callReadyStateChange(XMLHttpRequest.DONE)
|
|
168
|
-
|
|
169
|
-
|
|
208
|
+
const timeoutEvent = createXMLHttpRequestEvent('timeout', this, 0)
|
|
209
|
+
this.trigger('timeout', timeoutEvent)
|
|
210
|
+
isFunction(this.ontimeout) && this.ontimeout(timeoutEvent)
|
|
170
211
|
}
|
|
171
212
|
}, this.#timeout)
|
|
172
213
|
}
|
|
@@ -184,7 +225,8 @@ export class XMLHttpRequest extends Events {
|
|
|
184
225
|
|
|
185
226
|
// 头信息
|
|
186
227
|
const header = Object.assign({}, this.#header)
|
|
187
|
-
|
|
228
|
+
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
|
|
229
|
+
header.cookie = window.document.$$cookie
|
|
188
230
|
if (!this.withCredentials) {
|
|
189
231
|
// 不同源,要求 withCredentials 为 true 才携带 cookie
|
|
190
232
|
const { origin } = parseUrl(url)
|
|
@@ -255,11 +297,14 @@ export class XMLHttpRequest extends Events {
|
|
|
255
297
|
// 处理返回数据
|
|
256
298
|
if (data) {
|
|
257
299
|
this.#callReadyStateChange(XMLHttpRequest.LOADING)
|
|
258
|
-
|
|
259
|
-
|
|
300
|
+
const loadstartEvent = createXMLHttpRequestEvent('loadstart', this, header['Content-Length'])
|
|
301
|
+
this.trigger('loadstart', loadstartEvent)
|
|
302
|
+
isFunction(this.onloadstart) && this.onloadstart(loadstartEvent)
|
|
260
303
|
this.#response = data
|
|
261
|
-
|
|
262
|
-
|
|
304
|
+
|
|
305
|
+
const loadEvent = createXMLHttpRequestEvent('load', this, header['Content-Length'])
|
|
306
|
+
this.trigger('load', loadEvent)
|
|
307
|
+
isFunction(this.onload) && this.onload(loadEvent)
|
|
263
308
|
}
|
|
264
309
|
}
|
|
265
310
|
|
|
@@ -267,10 +312,33 @@ export class XMLHttpRequest extends Events {
|
|
|
267
312
|
* 请求失败
|
|
268
313
|
*/
|
|
269
314
|
#requestFail (err) {
|
|
315
|
+
// 微信小程序,无论接口返回200还是其他,响应无论是否有错误,都会进入 success 回调;只有类似超时这种请求错误才会进入 fail 回调
|
|
316
|
+
//
|
|
317
|
+
/**
|
|
318
|
+
* 阿里系小程序,接口返回非200状态码,会进入 fail 回调, 此时 err 对象结构如下(当错误码为 14 或 19 时,会多返回 status、data、headers。可通过这些字段获取服务端相关错误信息):
|
|
319
|
+
{
|
|
320
|
+
data: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
321
|
+
error: 19
|
|
322
|
+
errorMessage: "http status error"
|
|
323
|
+
headers: {date: 'Mon, 14 Aug 2023 08:54:58 GMT', content-type: 'application/json;charset=UTF-8', content-length: '52', connection: 'close', access-control-allow-credentials: 'true', …}
|
|
324
|
+
originalData: "{\"code\": 401,\"msg\":\"登录过期,请重新登录\"}"
|
|
325
|
+
status: 401
|
|
326
|
+
}
|
|
327
|
+
*/
|
|
328
|
+
// 统一行为,能正常响应的,都算 success.
|
|
329
|
+
if (err.status) {
|
|
330
|
+
this.#requestSuccess({
|
|
331
|
+
data: err,
|
|
332
|
+
statusCode: err.status,
|
|
333
|
+
header: err.headers
|
|
334
|
+
})
|
|
335
|
+
return
|
|
336
|
+
}
|
|
270
337
|
this.#status = 0
|
|
271
|
-
this.#statusText = err.errMsg
|
|
272
|
-
|
|
273
|
-
|
|
338
|
+
this.#statusText = err.errMsg || err.errorMessage
|
|
339
|
+
const errorEvent = createXMLHttpRequestEvent('error', this, 0)
|
|
340
|
+
this.trigger('error', errorEvent)
|
|
341
|
+
isFunction(this.onerror) && this.onerror(errorEvent)
|
|
274
342
|
}
|
|
275
343
|
|
|
276
344
|
/**
|
|
@@ -281,8 +349,9 @@ export class XMLHttpRequest extends Events {
|
|
|
281
349
|
this.#callReadyStateChange(XMLHttpRequest.DONE)
|
|
282
350
|
|
|
283
351
|
if (this.#status) {
|
|
284
|
-
|
|
285
|
-
|
|
352
|
+
const loadendEvent = createXMLHttpRequestEvent('loadend', this, this.#header['Content-Length'])
|
|
353
|
+
this.trigger('loadend', loadendEvent)
|
|
354
|
+
isFunction(this.onloadend) && this.onloadend(loadendEvent)
|
|
286
355
|
}
|
|
287
356
|
}
|
|
288
357
|
|
|
@@ -346,8 +415,9 @@ export class XMLHttpRequest extends Events {
|
|
|
346
415
|
abort () {
|
|
347
416
|
if (this.#requestTask) {
|
|
348
417
|
this.#requestTask.abort()
|
|
349
|
-
|
|
350
|
-
|
|
418
|
+
const abortEvent = createXMLHttpRequestEvent('abort', this, 0)
|
|
419
|
+
this.trigger('abort', abortEvent)
|
|
420
|
+
isFunction(this.onabort) && this.onabort(abortEvent)
|
|
351
421
|
}
|
|
352
422
|
}
|
|
353
423
|
|
package/src/runtime/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { document, window } from '@tarojs/runtime'
|
|
|
2
2
|
import { isWebPlatform } from '@tarojs/shared'
|
|
3
3
|
|
|
4
4
|
import { Cookie, createCookieInstance } from './Cookie'
|
|
5
|
-
import { XMLHttpRequest } from './XMLHttpRequest'
|
|
5
|
+
import { type XMLHttpRequestEvent, XMLHttpRequest } from './XMLHttpRequest'
|
|
6
6
|
|
|
7
7
|
declare const ENABLE_COOKIE: boolean
|
|
8
8
|
|
|
@@ -26,10 +26,16 @@ if (!isWebPlatform()) {
|
|
|
26
26
|
_cookie.setCookie(value, this.URL)
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
|
+
/** 获取完整的 cookie,包括 httpOnly 也能获取到 */
|
|
30
|
+
$$cookie: {
|
|
31
|
+
get () {
|
|
32
|
+
return _cookie.getCookie(this.URL, true)
|
|
33
|
+
},
|
|
34
|
+
}
|
|
29
35
|
})
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
window.XMLHttpRequest = XMLHttpRequest
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
export { Cookie, document, XMLHttpRequest }
|
|
41
|
+
export { Cookie, document, XMLHttpRequest, XMLHttpRequestEvent }
|