UNPKG

5.84 kBJavaScriptView Raw
1import {
2 onAndSyncApis,
3 noPromiseApis,
4 otherApis,
5 initPxTransform,
6 Link
7} from '@tarojs/taro'
8import { cacheDataSet, cacheDataGet } from './data-cache'
9import { queryToJson, getUniqueKey } from './util'
10
11const RequestQueue = {
12 MAX_REQUEST: 5,
13 queue: [],
14 pendingQueue: [],
15
16 request (options) {
17 this.queue.push(options)
18 return this.run()
19 },
20
21 run () {
22 if (!this.queue.length) return
23
24 while (this.pendingQueue.length < this.MAX_REQUEST) {
25 const options = this.queue.shift()
26 let successFn = options.success
27 let failFn = options.fail
28 options.success = (...args) => {
29 this.pendingQueue = this.pendingQueue.filter(item => item !== options)
30 this.run()
31 successFn && successFn.apply(options, args)
32 }
33 options.fail = (...args) => {
34 this.pendingQueue = this.pendingQueue.filter(item => item !== options)
35 this.run()
36 failFn && failFn.apply(options, args)
37 }
38 this.pendingQueue.push(options)
39 return tt.request(options)
40 }
41 }
42}
43
44function taroInterceptor (chain) {
45 return request(chain.requestParams)
46}
47
48const link = new Link(taroInterceptor)
49
50function request (options) {
51 options = options || {}
52 if (typeof options === 'string') {
53 options = {
54 url: options
55 }
56 }
57 const originSuccess = options['success']
58 const originFail = options['fail']
59 const originComplete = options['complete']
60 let requestTask
61 const p = new Promise((resolve, reject) => {
62 options['success'] = res => {
63 originSuccess && originSuccess(res)
64 resolve(res)
65 }
66 options['fail'] = res => {
67 originFail && originFail(res)
68 reject(res)
69 }
70
71 options['complete'] = res => {
72 originComplete && originComplete(res)
73 }
74
75 requestTask = RequestQueue.request(options)
76 })
77 p.abort = (cb) => {
78 cb && cb()
79 if (requestTask) {
80 requestTask.abort()
81 }
82 return p
83 }
84 return p
85}
86
87function processApis (taro) {
88 const weApis = Object.assign({ }, onAndSyncApis, noPromiseApis, otherApis)
89 const preloadPrivateKey = '__preload_'
90 const preloadInitedComponent = '$preloadComponent'
91 Object.keys(weApis).forEach(key => {
92 if (!(key in tt)) {
93 taro[key] = () => {
94 console.warn(`头条小程序暂不支持 ${key}`)
95 }
96 return
97 }
98 if (!onAndSyncApis[key] && !noPromiseApis[key]) {
99 taro[key] = (options, ...args) => {
100 options = options || {}
101 let task = null
102 let obj = Object.assign({}, options)
103 if (typeof options === 'string') {
104 if (args.length) {
105 return tt[key](options, ...args)
106 }
107 return tt[key](options)
108 }
109
110 if (key === 'navigateTo' || key === 'redirectTo') {
111 let url = obj['url'] ? obj['url'].replace(/^\//, '') : ''
112 if (url.indexOf('?') > -1) url = url.split('?')[0]
113
114 const Component = cacheDataGet(url)
115 if (Component) {
116 const component = new Component()
117 if (component.componentWillPreload) {
118 const cacheKey = getUniqueKey()
119 const MarkIndex = obj.url.indexOf('?')
120 const hasMark = MarkIndex > -1
121 const urlQueryStr = hasMark ? obj.url.substring(MarkIndex + 1, obj.url.length) : ''
122 const params = queryToJson(urlQueryStr)
123 obj.url += (hasMark ? '&' : '?') + `${preloadPrivateKey}=${cacheKey}`
124 cacheDataSet(cacheKey, component.componentWillPreload(params))
125 cacheDataSet(preloadInitedComponent, component)
126 }
127 }
128 }
129
130 const p = new Promise((resolve, reject) => {
131 ['fail', 'success', 'complete'].forEach((k) => {
132 obj[k] = (res) => {
133 options[k] && options[k](res)
134 if (k === 'success') {
135 if (key === 'connectSocket') {
136 resolve(
137 Promise.resolve().then(() => Object.assign(task, res))
138 )
139 } else {
140 resolve(res)
141 }
142 } else if (k === 'fail') {
143 reject(res)
144 }
145 }
146 })
147 if (args.length) {
148 task = tt[key](obj, ...args)
149 } else {
150 task = tt[key](obj)
151 }
152 })
153 if (key === 'uploadFile' || key === 'downloadFile') {
154 p.progress = cb => {
155 if (task) {
156 task.onProgressUpdate(cb)
157 }
158 return p
159 }
160 p.abort = cb => {
161 cb && cb()
162 if (task) {
163 task.abort()
164 }
165 return p
166 }
167 }
168 return p
169 }
170 } else {
171 taro[key] = (...args) => {
172 const argsLen = args.length
173 const newArgs = args.concat()
174 const lastArg = newArgs[argsLen - 1]
175 if (lastArg && lastArg.isTaroComponent && lastArg.$scope) {
176 newArgs.splice(argsLen - 1, 1, lastArg.$scope)
177 }
178 return tt[key].apply(tt, newArgs)
179 }
180 }
181 })
182}
183
184function pxTransform (size) {
185 const {
186 designWidth = 750,
187 deviceRatio = {
188 '640': 2.34 / 2,
189 '750': 1,
190 '828': 1.81 / 2
191 }
192 } = this.config || {}
193 if (!(designWidth in deviceRatio)) {
194 throw new Error(`deviceRatio 配置中不存在 ${designWidth} 的设置!`)
195 }
196 return parseInt(size, 10) / deviceRatio[designWidth] + 'rpx'
197}
198
199export default function initNativeApi (taro) {
200 processApis(taro)
201 taro.request = link.request.bind(link)
202 taro.addInterceptor = link.addInterceptor.bind(link)
203 taro.cleanInterceptors = link.cleanInterceptors.bind(link)
204 taro.getCurrentPages = getCurrentPages
205 taro.getApp = getApp
206 taro.initPxTransform = initPxTransform.bind(taro)
207 taro.pxTransform = pxTransform.bind(taro)
208}