@tarojs/taro-h5 3.4.0-beta.2 → 3.4.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.
- package/dist/api/ad/index.js +4 -0
- package/dist/api/ai/facial.js +5 -0
- package/dist/api/ai/index.js +2 -0
- package/dist/api/ai/visual.js +5 -0
- package/dist/api/alipay/index.js +3 -0
- package/dist/api/base/crypto.js +3 -0
- package/dist/api/base/debug.js +4 -0
- package/dist/api/base/index.js +17 -0
- package/dist/api/base/performance.js +4 -0
- package/dist/api/base/system.js +187 -0
- package/dist/api/base/update.js +4 -0
- package/dist/api/base/weapp/app-event.js +18 -0
- package/dist/api/base/weapp/life-cycle.js +4 -0
- package/dist/api/canvas/CanvasContext.js +191 -0
- package/dist/api/canvas/canvasGetImageData.js +25 -0
- package/dist/api/canvas/canvasPutImageData.js +22 -0
- package/dist/api/canvas/canvasToTempFilePath.js +22 -0
- package/dist/api/canvas/createCanvasContext.js +16 -0
- package/dist/api/canvas/index.js +12 -0
- package/dist/api/cloud/index.js +21 -0
- package/dist/api/data-analysis/index.js +5 -0
- package/dist/api/device/accelerometer.js +83 -0
- package/dist/api/device/accessibility.js +3 -0
- package/dist/api/device/battery.js +21 -0
- package/dist/api/device/bluetooth-ble.js +18 -0
- package/dist/api/device/bluetooth-peripheral.js +5 -0
- package/dist/api/device/bluetooth.js +15 -0
- package/dist/api/device/calendar.js +4 -0
- package/dist/api/device/clipboard.js +65 -0
- package/dist/api/device/compass.js +64 -0
- package/dist/api/device/contact.js +4 -0
- package/dist/api/device/crypto.js +3 -0
- package/dist/api/device/gyroscope.js +6 -0
- package/dist/api/device/iBeacon.js +9 -0
- package/dist/api/device/index.js +23 -0
- package/dist/api/device/keyboard.js +6 -0
- package/dist/api/device/memory.js +4 -0
- package/dist/api/device/motion.js +81 -0
- package/dist/api/device/network.js +78 -0
- package/dist/api/device/nfc.js +9 -0
- package/dist/api/device/phone.js +24 -0
- package/dist/api/device/scan.js +6 -0
- package/dist/api/device/screen.js +8 -0
- package/dist/api/device/vibrate.js +35 -0
- package/dist/api/device/wifi.js +13 -0
- package/dist/api/ext/index.js +4 -0
- package/dist/api/files/index.js +10 -0
- package/dist/api/framework/index.js +7 -0
- package/dist/api/index.js +24 -0
- package/dist/api/location/chooseLocation.js +93 -0
- package/dist/api/location/index.js +13 -0
- package/dist/api/location/style.css +79 -0
- package/dist/api/media/EditorContext.js +19 -0
- package/dist/api/media/audio/InnerAudioContext.js +84 -0
- package/dist/api/media/audio/index.js +15 -0
- package/dist/api/media/background-audio/BackgroundAudioManager.js +86 -0
- package/dist/api/media/background-audio/index.js +15 -0
- package/dist/api/media/camera.js +3 -0
- package/dist/api/media/image/chooseImage.js +74 -0
- package/dist/api/media/image/getImageInfo.js +31 -0
- package/dist/api/media/image/index.js +9 -0
- package/dist/api/media/image/previewImage.js +67 -0
- package/dist/api/media/index.js +12 -0
- package/dist/api/media/live.js +4 -0
- package/dist/api/media/map.js +3 -0
- package/dist/api/media/media-recorder.js +3 -0
- package/dist/api/media/recorder.js +5 -0
- package/dist/api/media/video/index.js +74 -0
- package/dist/api/media/video-decoder.js +3 -0
- package/dist/api/media/video-processing.js +3 -0
- package/dist/api/media/voip.js +16 -0
- package/dist/api/navigate/index.js +6 -0
- package/dist/api/network/download.js +124 -0
- package/dist/api/network/index.js +7 -0
- package/dist/api/network/mdns.js +12 -0
- package/dist/api/network/request/index.js +125 -0
- package/dist/api/network/tcp.js +3 -0
- package/dist/api/network/udp.js +3 -0
- package/dist/api/network/upload.js +146 -0
- package/dist/api/network/utils.js +65 -0
- package/dist/api/network/websocket/index.js +70 -0
- package/dist/api/network/websocket/socketTask.js +63 -0
- package/dist/api/open-api/account.js +3 -0
- package/dist/api/open-api/address.js +3 -0
- package/dist/api/open-api/authorize.js +4 -0
- package/dist/api/open-api/card.js +4 -0
- package/dist/api/open-api/channels-live.js +8 -0
- package/dist/api/open-api/customer-service.js +3 -0
- package/dist/api/open-api/facial.js +6 -0
- package/dist/api/open-api/favorites.js +4 -0
- package/dist/api/open-api/group.js +3 -0
- package/dist/api/open-api/index.js +18 -0
- package/dist/api/open-api/invoice.js +4 -0
- package/dist/api/open-api/license-plate.js +3 -0
- package/dist/api/open-api/login.js +5 -0
- package/dist/api/open-api/red-package.js +3 -0
- package/dist/api/open-api/settings.js +4 -0
- package/dist/api/open-api/soter.js +5 -0
- package/dist/api/open-api/subscribe-message.js +3 -0
- package/dist/api/open-api/user-info.js +4 -0
- package/dist/api/open-api/werun.js +4 -0
- package/dist/api/payment/index.js +4 -0
- package/dist/api/route/index.js +3 -0
- package/dist/api/share/index.js +12 -0
- package/dist/api/storage/background-fetch.js +6 -0
- package/dist/api/storage/index.js +157 -0
- package/dist/api/swan/index.js +26 -0
- package/dist/api/taro.js +47 -0
- package/dist/api/ui/animation/index.js +288 -0
- package/dist/api/ui/background.js +4 -0
- package/dist/api/ui/custom-component.js +3 -0
- package/dist/api/ui/fonts.js +51 -0
- package/dist/api/ui/index.js +12 -0
- package/dist/api/ui/interaction/actionSheet.js +188 -0
- package/dist/api/ui/interaction/index.js +268 -0
- package/dist/api/ui/interaction/modal.js +207 -0
- package/dist/api/ui/interaction/toast.js +195 -0
- package/dist/api/ui/menu.js +3 -0
- package/dist/api/ui/navigation-bar/index.js +42 -0
- package/dist/api/ui/pull-down-refresh.js +26 -0
- package/dist/api/ui/scroll/index.js +83 -0
- package/dist/api/ui/sticky.js +3 -0
- package/dist/api/ui/tab-bar.js +282 -0
- package/dist/api/ui/window.js +31 -0
- package/dist/api/utils/handler.js +80 -0
- package/dist/api/utils/index.js +172 -0
- package/dist/api/worker/index.js +3 -0
- package/dist/api/wxml/index.js +6 -0
- package/dist/api/wxml/nodesRef.js +42 -0
- package/dist/api/wxml/selectorQuery.js +201 -0
- package/dist/index.cjs.js +5028 -6988
- package/dist/index.js +4 -10767
- package/dist/taroApis.js +1 -1
- package/dist/types/type.js +2 -0
- package/package.json +11 -13
- package/src/api/ai/visual.ts +3 -0
- package/src/api/base/system.ts +207 -0
- package/src/api/canvas/CanvasContext.ts +42 -39
- package/src/api/canvas/createCanvasContext.ts +2 -2
- package/src/api/canvas/index.ts +10 -2
- package/src/api/cloud/index.ts +4 -0
- package/src/api/device/battery.ts +18 -1
- package/src/api/device/index.ts +1 -0
- package/src/api/{base/system → device}/network.ts +35 -15
- package/src/api/device/wifi.ts +1 -0
- package/src/api/location/chooseLocation.ts +2 -2
- package/src/api/media/{editor.ts → EditorContext.ts} +2 -0
- package/src/api/media/audio/InnerAudioContext.ts +98 -0
- package/src/api/media/audio/index.ts +1 -86
- package/src/api/media/background-audio/BackgroundAudioManager.ts +103 -0
- package/src/api/media/{background-audio.ts → background-audio/index.ts} +7 -2
- package/src/api/media/image/previewImage.ts +4 -25
- package/src/api/media/index.ts +0 -1
- package/src/api/network/download.ts +5 -5
- package/src/api/network/upload.ts +7 -13
- package/src/api/network/websocket/index.ts +1 -1
- package/src/api/ui/animation/index.ts +11 -12
- package/src/api/ui/fonts.ts +61 -2
- package/src/api/ui/interaction/index.ts +12 -10
- package/src/api/ui/navigation-bar/index.ts +2 -2
- package/src/api/ui/scroll/index.ts +3 -3
- package/src/api/utils/handler.ts +4 -4
- package/src/api/utils/index.ts +34 -13
- package/src/api/wxml/nodesRef.ts +10 -3
- package/src/api/wxml/selectorQuery.ts +68 -23
- package/src/index.ts +2 -2
- package/src/api/base/system/index.ts +0 -2
- package/src/api/base/system/info.ts +0 -64
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { MethodHandler } from '../../utils/handler';
|
|
2
|
+
import { findDOM, shouldBeObject, temporarilyNotSupport } from '../../utils';
|
|
3
|
+
// 视频
|
|
4
|
+
export const saveVideoToPhotosAlbum = temporarilyNotSupport('saveVideoToPhotosAlbum');
|
|
5
|
+
export const openVideoEditor = temporarilyNotSupport('openVideoEditor');
|
|
6
|
+
export const getVideoInfo = temporarilyNotSupport('getVideoInfo');
|
|
7
|
+
/**
|
|
8
|
+
* 创建 video 上下文 VideoContext 对象。
|
|
9
|
+
*/
|
|
10
|
+
export const createVideoContext = (id, inst) => {
|
|
11
|
+
const el = findDOM(inst);
|
|
12
|
+
// TODO HTMLVideoElement to VideoContext
|
|
13
|
+
return el === null || el === void 0 ? void 0 : el.querySelector(`taro-video-core[id=${id}]`);
|
|
14
|
+
};
|
|
15
|
+
export const compressVideo = temporarilyNotSupport('compressVideo');
|
|
16
|
+
/**
|
|
17
|
+
* 拍摄视频或从手机相册中选视频。
|
|
18
|
+
*/
|
|
19
|
+
export const chooseVideo = (options) => {
|
|
20
|
+
// options must be an Object
|
|
21
|
+
const isObject = shouldBeObject(options);
|
|
22
|
+
if (!isObject.flag) {
|
|
23
|
+
const res = { errMsg: `chooseVideo:fail ${isObject.msg}` };
|
|
24
|
+
console.error(res.errMsg);
|
|
25
|
+
return Promise.reject(res);
|
|
26
|
+
}
|
|
27
|
+
const { success, fail, complete } = options;
|
|
28
|
+
const handle = new MethodHandler({ name: 'chooseVideo', success, fail, complete });
|
|
29
|
+
const res = {
|
|
30
|
+
tempFilePath: '',
|
|
31
|
+
duration: 0,
|
|
32
|
+
size: 0,
|
|
33
|
+
height: 0,
|
|
34
|
+
width: 0
|
|
35
|
+
};
|
|
36
|
+
const inputEl = document.createElement('input');
|
|
37
|
+
inputEl.setAttribute('type', 'file');
|
|
38
|
+
inputEl.setAttribute('multiple', 'multiple');
|
|
39
|
+
inputEl.setAttribute('accept', 'video/*');
|
|
40
|
+
inputEl.setAttribute('style', 'position: fixed; top: -4000px; left: -3000px; z-index: -300;');
|
|
41
|
+
document.body.appendChild(inputEl);
|
|
42
|
+
return new Promise(resolve => {
|
|
43
|
+
const TaroMouseEvents = document.createEvent('MouseEvents');
|
|
44
|
+
TaroMouseEvents.initEvent('click', true, true);
|
|
45
|
+
inputEl.dispatchEvent(TaroMouseEvents);
|
|
46
|
+
inputEl.onchange = function (e) {
|
|
47
|
+
var _a;
|
|
48
|
+
const target = e.target;
|
|
49
|
+
const file = (_a = target.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
50
|
+
const reader = new FileReader();
|
|
51
|
+
reader.onload = function (event) {
|
|
52
|
+
var _a;
|
|
53
|
+
const videoEl = document.createElement('video');
|
|
54
|
+
const url = (_a = event.target) === null || _a === void 0 ? void 0 : _a.result;
|
|
55
|
+
videoEl.preload = 'metadata';
|
|
56
|
+
videoEl.src = url;
|
|
57
|
+
videoEl.onloadedmetadata = () => {
|
|
58
|
+
res.tempFilePath = url;
|
|
59
|
+
res.duration = videoEl.duration;
|
|
60
|
+
res.size = event.total;
|
|
61
|
+
res.height = videoEl.videoHeight;
|
|
62
|
+
res.width = videoEl.videoHeight;
|
|
63
|
+
return handle.success(res, resolve);
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
if (file) {
|
|
67
|
+
reader.readAsDataURL(file);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}).finally(() => {
|
|
71
|
+
document.body.removeChild(inputEl);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
export const chooseMedia = temporarilyNotSupport('chooseMedia');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { temporarilyNotSupport } from '../utils';
|
|
2
|
+
// 实时语音
|
|
3
|
+
export const updateVoIPChatMuteConfig = temporarilyNotSupport('updateVoIPChatMuteConfig');
|
|
4
|
+
export const subscribeVoIPVideoMembers = temporarilyNotSupport('subscribeVoIPVideoMembers');
|
|
5
|
+
export const setEnable1v1Chat = temporarilyNotSupport('setEnable1v1Chat');
|
|
6
|
+
export const onVoIPVideoMembersChanged = temporarilyNotSupport('onVoIPVideoMembersChanged');
|
|
7
|
+
export const onVoIPChatStateChanged = temporarilyNotSupport('onVoIPChatStateChanged');
|
|
8
|
+
export const onVoIPChatSpeakersChanged = temporarilyNotSupport('onVoIPChatSpeakersChanged');
|
|
9
|
+
export const onVoIPChatMembersChanged = temporarilyNotSupport('onVoIPChatMembersChanged');
|
|
10
|
+
export const onVoIPChatInterrupted = temporarilyNotSupport('onVoIPChatInterrupted');
|
|
11
|
+
export const offVoIPVideoMembersChanged = temporarilyNotSupport('offVoIPVideoMembersChanged');
|
|
12
|
+
export const offVoIPChatStateChanged = temporarilyNotSupport('offVoIPChatStateChanged');
|
|
13
|
+
export const offVoIPChatMembersChanged = temporarilyNotSupport('offVoIPChatMembersChanged');
|
|
14
|
+
export const offVoIPChatInterrupted = temporarilyNotSupport('offVoIPChatInterrupted');
|
|
15
|
+
export const joinVoIPChat = temporarilyNotSupport('joinVoIPChat');
|
|
16
|
+
export const exitVoIPChat = temporarilyNotSupport('exitVoIPChat');
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { temporarilyNotSupport } from '../utils';
|
|
2
|
+
// 跳转
|
|
3
|
+
export const openEmbeddedMiniProgram = temporarilyNotSupport('openEmbeddedMiniProgram');
|
|
4
|
+
export const navigateToMiniProgram = temporarilyNotSupport('navigateToMiniProgram');
|
|
5
|
+
export const navigateBackMiniProgram = temporarilyNotSupport('navigateBackMiniProgram');
|
|
6
|
+
export const exitMiniProgram = temporarilyNotSupport('exitMiniProgram');
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { CallbackManager } from '../utils/handler';
|
|
2
|
+
import { NETWORK_TIMEOUT, setHeader, XHR_STATS } from './utils';
|
|
3
|
+
const createDownloadTask = ({ url, header, success, error }) => {
|
|
4
|
+
let timeout;
|
|
5
|
+
const apiName = 'downloadFile';
|
|
6
|
+
const xhr = new XMLHttpRequest();
|
|
7
|
+
const callbackManager = {
|
|
8
|
+
headersReceived: new CallbackManager(),
|
|
9
|
+
progressUpdate: new CallbackManager()
|
|
10
|
+
};
|
|
11
|
+
xhr.open('GET', url, true);
|
|
12
|
+
xhr.responseType = 'blob';
|
|
13
|
+
setHeader(xhr, header);
|
|
14
|
+
xhr.onprogress = e => {
|
|
15
|
+
const { loaded, total } = e;
|
|
16
|
+
callbackManager.progressUpdate.trigger({
|
|
17
|
+
progress: Math.round(loaded / total * 100),
|
|
18
|
+
totalBytesWritten: loaded,
|
|
19
|
+
totalBytesExpectedToWrite: total
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
xhr.onreadystatechange = () => {
|
|
23
|
+
if (xhr.readyState !== XHR_STATS.HEADERS_RECEIVED)
|
|
24
|
+
return;
|
|
25
|
+
callbackManager.headersReceived.trigger({
|
|
26
|
+
header: xhr.getAllResponseHeaders()
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
xhr.onload = () => {
|
|
30
|
+
const response = xhr.response;
|
|
31
|
+
const status = xhr.status;
|
|
32
|
+
success({
|
|
33
|
+
errMsg: `${apiName}:ok`,
|
|
34
|
+
statusCode: status,
|
|
35
|
+
tempFilePath: window.URL.createObjectURL(response)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
xhr.onabort = () => {
|
|
39
|
+
clearTimeout(timeout);
|
|
40
|
+
error({
|
|
41
|
+
errMsg: `${apiName}:fail abort`
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
xhr.onerror = (e) => {
|
|
45
|
+
error({
|
|
46
|
+
errMsg: `${apiName}:fail ${e.message}`
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* 中断任务
|
|
51
|
+
*/
|
|
52
|
+
const abort = () => {
|
|
53
|
+
xhr.abort();
|
|
54
|
+
};
|
|
55
|
+
const send = () => {
|
|
56
|
+
xhr.send();
|
|
57
|
+
timeout = setTimeout(() => {
|
|
58
|
+
xhr.onabort = null;
|
|
59
|
+
xhr.onload = null;
|
|
60
|
+
xhr.onprogress = null;
|
|
61
|
+
xhr.onreadystatechange = null;
|
|
62
|
+
xhr.onerror = null;
|
|
63
|
+
abort();
|
|
64
|
+
error({
|
|
65
|
+
errMsg: `${apiName}:fail timeout`
|
|
66
|
+
});
|
|
67
|
+
}, NETWORK_TIMEOUT);
|
|
68
|
+
};
|
|
69
|
+
send();
|
|
70
|
+
/**
|
|
71
|
+
* 监听 HTTP Response Header 事件。会比请求完成事件更早
|
|
72
|
+
* @param {HeadersReceivedCallback} callback HTTP Response Header 事件的回调函数
|
|
73
|
+
*/
|
|
74
|
+
const onHeadersReceived = callbackManager.headersReceived.add;
|
|
75
|
+
/**
|
|
76
|
+
* 取消监听 HTTP Response Header 事件
|
|
77
|
+
* @param {HeadersReceivedCallback} callback HTTP Response Header 事件的回调函数
|
|
78
|
+
*/
|
|
79
|
+
const offHeadersReceived = callbackManager.headersReceived.remove;
|
|
80
|
+
/**
|
|
81
|
+
* 监听进度变化事件
|
|
82
|
+
* @param {ProgressUpdateCallback} callback HTTP Response Header 事件的回调函数
|
|
83
|
+
*/
|
|
84
|
+
const onProgressUpdate = callbackManager.progressUpdate.add;
|
|
85
|
+
/**
|
|
86
|
+
* 取消监听进度变化事件
|
|
87
|
+
* @param {ProgressUpdateCallback} callback HTTP Response Header 事件的回调函数
|
|
88
|
+
*/
|
|
89
|
+
const offProgressUpdate = callbackManager.progressUpdate.remove;
|
|
90
|
+
return {
|
|
91
|
+
abort,
|
|
92
|
+
onHeadersReceived,
|
|
93
|
+
offHeadersReceived,
|
|
94
|
+
onProgressUpdate,
|
|
95
|
+
offProgressUpdate
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* 下载文件资源到本地。客户端直接发起一个 HTTPS GET 请求,返回文件的本地临时路径。使用前请注意阅读相关说明。
|
|
100
|
+
* 注意:请在服务端响应的 header 中指定合理的 Content-Type 字段,以保证客户端正确处理文件类型。
|
|
101
|
+
*/
|
|
102
|
+
export const downloadFile = ({ url, header, success, fail, complete }) => {
|
|
103
|
+
let task;
|
|
104
|
+
const result = new Promise((resolve, reject) => {
|
|
105
|
+
task = createDownloadTask({
|
|
106
|
+
url,
|
|
107
|
+
header,
|
|
108
|
+
success: res => {
|
|
109
|
+
success && success(res);
|
|
110
|
+
complete && complete(res);
|
|
111
|
+
resolve(res);
|
|
112
|
+
},
|
|
113
|
+
error: res => {
|
|
114
|
+
fail && fail(res);
|
|
115
|
+
complete && complete(res);
|
|
116
|
+
reject(res);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
result.headersReceive = task.onHeadersReceived;
|
|
121
|
+
result.progress = task.onProgressUpdate;
|
|
122
|
+
result.abort = task.abort;
|
|
123
|
+
return result;
|
|
124
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { temporarilyNotSupport } from '../utils';
|
|
2
|
+
// mDNS
|
|
3
|
+
export const stopLocalServiceDiscovery = temporarilyNotSupport('stopLocalServiceDiscovery');
|
|
4
|
+
export const startLocalServiceDiscovery = temporarilyNotSupport('startLocalServiceDiscovery');
|
|
5
|
+
export const onLocalServiceResolveFail = temporarilyNotSupport('onLocalServiceResolveFail');
|
|
6
|
+
export const onLocalServiceLost = temporarilyNotSupport('onLocalServiceLost');
|
|
7
|
+
export const onLocalServiceFound = temporarilyNotSupport('onLocalServiceFound');
|
|
8
|
+
export const onLocalServiceDiscoveryStop = temporarilyNotSupport('onLocalServiceDiscoveryStop');
|
|
9
|
+
export const offLocalServiceResolveFail = temporarilyNotSupport('offLocalServiceResolveFail');
|
|
10
|
+
export const offLocalServiceLost = temporarilyNotSupport('offLocalServiceLost');
|
|
11
|
+
export const offLocalServiceFound = temporarilyNotSupport('offLocalServiceFound');
|
|
12
|
+
export const offLocalServiceDiscoveryStop = temporarilyNotSupport('offLocalServiceDiscoveryStop');
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import Taro from '@tarojs/api';
|
|
2
|
+
import 'whatwg-fetch';
|
|
3
|
+
import jsonpRetry from 'jsonp-retry';
|
|
4
|
+
import { serializeParams } from '../../utils';
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const { Link } = Taro;
|
|
7
|
+
function generateRequestUrlWithParams(url, params) {
|
|
8
|
+
params = typeof params === 'string' ? params : serializeParams(params);
|
|
9
|
+
if (params) {
|
|
10
|
+
url += (~url.indexOf('?') ? '&' : '?') + params;
|
|
11
|
+
}
|
|
12
|
+
url = url.replace('?&', '?');
|
|
13
|
+
return url;
|
|
14
|
+
}
|
|
15
|
+
// FIXME 移除 any 标注
|
|
16
|
+
function _request(options) {
|
|
17
|
+
options = options || {};
|
|
18
|
+
if (typeof options === 'string') {
|
|
19
|
+
options = {
|
|
20
|
+
url: options
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const { success, complete, fail } = options;
|
|
24
|
+
let url = options.url;
|
|
25
|
+
const params = {};
|
|
26
|
+
const res = {};
|
|
27
|
+
if (options.jsonp) {
|
|
28
|
+
Object.assign(params, options);
|
|
29
|
+
params.params = options.data;
|
|
30
|
+
params.cache = options.jsonpCache;
|
|
31
|
+
if (typeof options.jsonp === 'string') {
|
|
32
|
+
params.name = options.jsonp;
|
|
33
|
+
}
|
|
34
|
+
delete params.jsonp;
|
|
35
|
+
return jsonpRetry(url, params)
|
|
36
|
+
.then(data => {
|
|
37
|
+
res.statusCode = 200;
|
|
38
|
+
res.data = data;
|
|
39
|
+
typeof success === 'function' && success(res);
|
|
40
|
+
typeof complete === 'function' && complete(res);
|
|
41
|
+
return res;
|
|
42
|
+
})
|
|
43
|
+
.catch(err => {
|
|
44
|
+
typeof fail === 'function' && fail(err);
|
|
45
|
+
typeof complete === 'function' && complete(res);
|
|
46
|
+
return Promise.reject(err);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
params.method = options.method || 'GET';
|
|
50
|
+
const methodUpper = params.method.toUpperCase();
|
|
51
|
+
params.cache = options.cache || 'default';
|
|
52
|
+
if (methodUpper === 'GET' || methodUpper === 'HEAD') {
|
|
53
|
+
url = generateRequestUrlWithParams(url, options.data);
|
|
54
|
+
}
|
|
55
|
+
else if (typeof options.data === 'object') {
|
|
56
|
+
options.header = options.header || {};
|
|
57
|
+
const keyOfContentType = Object.keys(options.header).find(item => item.toLowerCase() === 'content-type');
|
|
58
|
+
if (!keyOfContentType) {
|
|
59
|
+
options.header['Content-Type'] = 'application/json';
|
|
60
|
+
}
|
|
61
|
+
const contentType = options.header[keyOfContentType || 'Content-Type'];
|
|
62
|
+
if (contentType.indexOf('application/json') >= 0) {
|
|
63
|
+
params.body = JSON.stringify(options.data);
|
|
64
|
+
}
|
|
65
|
+
else if (contentType.indexOf('application/x-www-form-urlencoded') >= 0) {
|
|
66
|
+
params.body = serializeParams(options.data);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
params.body = options.data;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
params.body = options.data;
|
|
74
|
+
}
|
|
75
|
+
if (options.header) {
|
|
76
|
+
params.headers = options.header;
|
|
77
|
+
}
|
|
78
|
+
if (options.mode) {
|
|
79
|
+
params.mode = options.mode;
|
|
80
|
+
}
|
|
81
|
+
if (options.signal) {
|
|
82
|
+
params.signal = options.signal;
|
|
83
|
+
}
|
|
84
|
+
params.credentials = options.credentials;
|
|
85
|
+
return fetch(url, params)
|
|
86
|
+
.then(response => {
|
|
87
|
+
res.statusCode = response.status;
|
|
88
|
+
res.header = {};
|
|
89
|
+
for (const key of response.headers.keys()) {
|
|
90
|
+
res.header[key] = response.headers.get(key);
|
|
91
|
+
}
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw response;
|
|
94
|
+
}
|
|
95
|
+
if (options.responseType === 'arraybuffer') {
|
|
96
|
+
return response.arrayBuffer();
|
|
97
|
+
}
|
|
98
|
+
if (res.statusCode !== 204) {
|
|
99
|
+
if (options.dataType === 'json' || typeof options.dataType === 'undefined') {
|
|
100
|
+
return response.json();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (options.responseType === 'text' || options.dataType === 'text') {
|
|
104
|
+
return response.text();
|
|
105
|
+
}
|
|
106
|
+
return Promise.resolve(null);
|
|
107
|
+
})
|
|
108
|
+
.then(data => {
|
|
109
|
+
res.data = data;
|
|
110
|
+
typeof success === 'function' && success(res);
|
|
111
|
+
typeof complete === 'function' && complete(res);
|
|
112
|
+
return res;
|
|
113
|
+
})
|
|
114
|
+
.catch(err => {
|
|
115
|
+
typeof fail === 'function' && fail(err);
|
|
116
|
+
typeof complete === 'function' && complete(res);
|
|
117
|
+
return Promise.reject(err);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function taroInterceptor(chain) {
|
|
121
|
+
return _request(chain.requestParams);
|
|
122
|
+
}
|
|
123
|
+
const link = new Link(taroInterceptor);
|
|
124
|
+
export const request = link.request.bind(link);
|
|
125
|
+
export const addInterceptor = link.addInterceptor.bind(link);
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { CallbackManager } from '../utils/handler';
|
|
2
|
+
import { convertObjectUrlToBlob, NETWORK_TIMEOUT, setHeader, XHR_STATS } from './utils';
|
|
3
|
+
const createUploadTask = ({ url, filePath, formData = {}, name, header, timeout, fileName, success, error }) => {
|
|
4
|
+
let timeoutInter;
|
|
5
|
+
let formKey;
|
|
6
|
+
const apiName = 'uploadFile';
|
|
7
|
+
const xhr = new XMLHttpRequest();
|
|
8
|
+
const form = new FormData();
|
|
9
|
+
const callbackManager = {
|
|
10
|
+
headersReceived: new CallbackManager(),
|
|
11
|
+
progressUpdate: new CallbackManager()
|
|
12
|
+
};
|
|
13
|
+
xhr.open('POST', url);
|
|
14
|
+
setHeader(xhr, header);
|
|
15
|
+
for (formKey in formData) {
|
|
16
|
+
form.append(formKey, formData[formKey]);
|
|
17
|
+
}
|
|
18
|
+
xhr.upload.onprogress = e => {
|
|
19
|
+
const { loaded, total } = e;
|
|
20
|
+
callbackManager.progressUpdate.trigger({
|
|
21
|
+
progress: Math.round(loaded / total * 100),
|
|
22
|
+
totalBytesSent: loaded,
|
|
23
|
+
totalBytesExpectedToSent: total
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
xhr.onreadystatechange = () => {
|
|
27
|
+
if (xhr.readyState !== XHR_STATS.HEADERS_RECEIVED)
|
|
28
|
+
return;
|
|
29
|
+
callbackManager.headersReceived.trigger({
|
|
30
|
+
header: xhr.getAllResponseHeaders()
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
xhr.onload = () => {
|
|
34
|
+
const status = xhr.status;
|
|
35
|
+
clearTimeout(timeoutInter);
|
|
36
|
+
success({
|
|
37
|
+
errMsg: `${apiName}:ok`,
|
|
38
|
+
statusCode: status,
|
|
39
|
+
data: xhr.responseText || xhr.response
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
xhr.onabort = () => {
|
|
43
|
+
clearTimeout(timeoutInter);
|
|
44
|
+
error({
|
|
45
|
+
errMsg: `${apiName}:fail abort`
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
xhr.onerror = (e) => {
|
|
49
|
+
clearTimeout(timeoutInter);
|
|
50
|
+
error({
|
|
51
|
+
errMsg: `${apiName}:fail ${e.message}`
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* 中断任务
|
|
56
|
+
*/
|
|
57
|
+
const abort = () => {
|
|
58
|
+
clearTimeout(timeoutInter);
|
|
59
|
+
xhr.abort();
|
|
60
|
+
};
|
|
61
|
+
const send = () => {
|
|
62
|
+
xhr.send(form);
|
|
63
|
+
timeoutInter = setTimeout(() => {
|
|
64
|
+
xhr.onabort = null;
|
|
65
|
+
xhr.onload = null;
|
|
66
|
+
xhr.upload.onprogress = null;
|
|
67
|
+
xhr.onreadystatechange = null;
|
|
68
|
+
xhr.onerror = null;
|
|
69
|
+
abort();
|
|
70
|
+
error({
|
|
71
|
+
errMsg: `${apiName}:fail timeout`
|
|
72
|
+
});
|
|
73
|
+
}, timeout || NETWORK_TIMEOUT);
|
|
74
|
+
};
|
|
75
|
+
convertObjectUrlToBlob(filePath)
|
|
76
|
+
.then((fileObj) => {
|
|
77
|
+
if (!fileName) {
|
|
78
|
+
fileName = typeof fileObj !== 'string' && fileObj.name;
|
|
79
|
+
}
|
|
80
|
+
form.append(name, fileObj, fileName || `file-${Date.now()}`);
|
|
81
|
+
send();
|
|
82
|
+
})
|
|
83
|
+
.catch(e => {
|
|
84
|
+
error({
|
|
85
|
+
errMsg: `${apiName}:fail ${e.message}`
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
/**
|
|
89
|
+
* 监听 HTTP Response Header 事件。会比请求完成事件更早
|
|
90
|
+
* @param {HeadersReceivedCallback} callback HTTP Response Header 事件的回调函数
|
|
91
|
+
*/
|
|
92
|
+
const onHeadersReceived = callbackManager.headersReceived.add;
|
|
93
|
+
/**
|
|
94
|
+
* 取消监听 HTTP Response Header 事件
|
|
95
|
+
* @param {HeadersReceivedCallback} callback HTTP Response Header 事件的回调函数
|
|
96
|
+
*/
|
|
97
|
+
const offHeadersReceived = callbackManager.headersReceived.remove;
|
|
98
|
+
/**
|
|
99
|
+
* 监听进度变化事件
|
|
100
|
+
* @param {ProgressUpdateCallback} callback HTTP Response Header 事件的回调函数
|
|
101
|
+
*/
|
|
102
|
+
const onProgressUpdate = callbackManager.progressUpdate.add;
|
|
103
|
+
/**
|
|
104
|
+
* 取消监听进度变化事件
|
|
105
|
+
* @param {ProgressUpdateCallback} callback HTTP Response Header 事件的回调函数
|
|
106
|
+
*/
|
|
107
|
+
const offProgressUpdate = callbackManager.progressUpdate.remove;
|
|
108
|
+
return {
|
|
109
|
+
abort,
|
|
110
|
+
onHeadersReceived,
|
|
111
|
+
offHeadersReceived,
|
|
112
|
+
onProgressUpdate,
|
|
113
|
+
offProgressUpdate
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* 将本地资源上传到服务器。客户端发起一个 HTTPS POST 请求,其中 content-type 为 multipart/form-data。使用前请注意阅读相关说明。
|
|
118
|
+
*/
|
|
119
|
+
export const uploadFile = ({ url, filePath, name, header, formData, timeout, fileName, success, fail, complete }) => {
|
|
120
|
+
let task;
|
|
121
|
+
const result = new Promise((resolve, reject) => {
|
|
122
|
+
task = createUploadTask({
|
|
123
|
+
url,
|
|
124
|
+
header,
|
|
125
|
+
name,
|
|
126
|
+
filePath,
|
|
127
|
+
formData,
|
|
128
|
+
timeout,
|
|
129
|
+
fileName,
|
|
130
|
+
success: res => {
|
|
131
|
+
success && success(res);
|
|
132
|
+
complete && complete(res);
|
|
133
|
+
resolve(res);
|
|
134
|
+
},
|
|
135
|
+
error: res => {
|
|
136
|
+
fail && fail(res);
|
|
137
|
+
complete && complete(res);
|
|
138
|
+
reject(res);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
result.headersReceive = task.onHeadersReceived;
|
|
143
|
+
result.progress = task.onProgressUpdate;
|
|
144
|
+
result.abort = task.abort;
|
|
145
|
+
return result;
|
|
146
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Response Header 事件回调函数的参数
|
|
3
|
+
* @typedef {Object} HeadersReceivedParam
|
|
4
|
+
* @property {Object} header 开发者服务器返回的 HTTP Response Header
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* HTTP Response Header 事件的回调函数
|
|
8
|
+
* @callback HeadersReceivedCallback
|
|
9
|
+
* @param {HeadersReceivedParam} res 参数
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 进度变化回调函数的参数
|
|
13
|
+
* @typedef {Object} ProgressUpdateParam
|
|
14
|
+
* @property {number} progress 进度百分比
|
|
15
|
+
* @property {number} [totalBytesWritten] 已经下载的数据长度,单位 Bytes
|
|
16
|
+
* @property {number} [totalBytesSent] 已经上传的数据长度,单位 Bytes
|
|
17
|
+
* @property {number} [totalBytesExpectedToWrite] 预期需要下载的数据总长度,单位 Bytes
|
|
18
|
+
* @property {number} [totalBytesExpectedToSend] 预期需要上传的数据总长度,单位 Bytes
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* 进度变化事件的回调函数
|
|
22
|
+
* @callback ProgressUpdateCallback
|
|
23
|
+
* @param {ProgressUpdateParam} res 参数
|
|
24
|
+
*/
|
|
25
|
+
export const NETWORK_TIMEOUT = 60000;
|
|
26
|
+
export const XHR_STATS = {
|
|
27
|
+
UNSENT: 0,
|
|
28
|
+
OPENED: 1,
|
|
29
|
+
HEADERS_RECEIVED: 2,
|
|
30
|
+
LOADING: 3,
|
|
31
|
+
DONE: 4 // The operation is complete.
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* 设置xhr的header
|
|
35
|
+
* @param {XMLHttpRequest} xhr
|
|
36
|
+
* @param {Object} header
|
|
37
|
+
*/
|
|
38
|
+
export const setHeader = (xhr, header) => {
|
|
39
|
+
let headerKey;
|
|
40
|
+
for (headerKey in header) {
|
|
41
|
+
xhr.setRequestHeader(headerKey, header[headerKey]);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 将 blob url 转化为文件
|
|
46
|
+
* @param {string} url 要转换的 blob url
|
|
47
|
+
* @returns {Promise<File>}
|
|
48
|
+
*/
|
|
49
|
+
export const convertObjectUrlToBlob = url => {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const xhr = new XMLHttpRequest();
|
|
52
|
+
xhr.open('GET', url, true);
|
|
53
|
+
xhr.responseType = 'blob';
|
|
54
|
+
xhr.onload = function () {
|
|
55
|
+
if (this.status === 200) {
|
|
56
|
+
resolve(this.response);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
/* eslint-disable prefer-promise-reject-errors */
|
|
60
|
+
reject({ status: this.status });
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
xhr.send();
|
|
64
|
+
});
|
|
65
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { SocketTask } from './socketTask';
|
|
2
|
+
import { shouldBeObject, getParameterError } from '../../utils';
|
|
3
|
+
import { MethodHandler } from '../../utils/handler';
|
|
4
|
+
let socketTasks = [];
|
|
5
|
+
let socketsCounter = 1;
|
|
6
|
+
export function sendSocketMessage() {
|
|
7
|
+
console.warn('Deprecated.Please use socketTask.send instead.');
|
|
8
|
+
}
|
|
9
|
+
export function onSocketOpen() {
|
|
10
|
+
console.warn('Deprecated.Please use socketTask.onOpen instead.');
|
|
11
|
+
}
|
|
12
|
+
export function onSocketMessage() {
|
|
13
|
+
console.warn('Deprecated.Please use socketTask.onMessage instead.');
|
|
14
|
+
}
|
|
15
|
+
export function onSocketError() {
|
|
16
|
+
console.warn('Deprecated.Please use socketTask.onError instead.');
|
|
17
|
+
}
|
|
18
|
+
export function onSocketClose() {
|
|
19
|
+
console.warn('Deprecated.Please use socketTask.onClose instead.');
|
|
20
|
+
}
|
|
21
|
+
export function connectSocket(options) {
|
|
22
|
+
const name = 'connectSocket';
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
// options must be an Object
|
|
25
|
+
const isObject = shouldBeObject(options);
|
|
26
|
+
if (!isObject.flag) {
|
|
27
|
+
const res = { errMsg: `${name}:fail ${isObject.msg}` };
|
|
28
|
+
console.error(res.errMsg);
|
|
29
|
+
return reject(res);
|
|
30
|
+
}
|
|
31
|
+
const { url, protocols, success, fail, complete } = options;
|
|
32
|
+
const handle = new MethodHandler({ name, success, fail, complete });
|
|
33
|
+
// options.url must be String
|
|
34
|
+
if (typeof url !== 'string') {
|
|
35
|
+
return handle.fail({
|
|
36
|
+
errMsg: getParameterError({
|
|
37
|
+
para: 'url',
|
|
38
|
+
correct: 'String',
|
|
39
|
+
wrong: url
|
|
40
|
+
})
|
|
41
|
+
}, reject);
|
|
42
|
+
}
|
|
43
|
+
// options.url must be invalid
|
|
44
|
+
if (!url.startsWith('ws://') && !url.startsWith('wss://')) {
|
|
45
|
+
return handle.fail({
|
|
46
|
+
errMsg: `request:fail invalid url "${url}"`
|
|
47
|
+
}, reject);
|
|
48
|
+
}
|
|
49
|
+
// protocols must be array
|
|
50
|
+
const _protocols = Array.isArray(protocols) ? protocols : null;
|
|
51
|
+
// 2 connection at most
|
|
52
|
+
if (socketTasks.length > 1) {
|
|
53
|
+
return handle.fail({
|
|
54
|
+
errMsg: '同时最多发起 2 个 socket 请求,更多请参考文档。'
|
|
55
|
+
}, reject);
|
|
56
|
+
}
|
|
57
|
+
const task = new SocketTask(url, _protocols);
|
|
58
|
+
task._destroyWhenClose = function () {
|
|
59
|
+
socketTasks = socketTasks.filter(socketTask => socketTask !== this);
|
|
60
|
+
};
|
|
61
|
+
socketTasks.push(task);
|
|
62
|
+
handle.success({
|
|
63
|
+
socketTaskId: socketsCounter++
|
|
64
|
+
});
|
|
65
|
+
return resolve(task);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
export function closeSocket() {
|
|
69
|
+
console.warn('Deprecated.Please use socketTask.close instead.');
|
|
70
|
+
}
|