Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions docs-vitepress/guide/extend/api-proxy.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Api代理

> convert API at each end 各个平台之间 api 进行转换,目前已支持微信转支付宝、微信转web
> convert API at each end 各个平台之间 api 进行转换,目前已支持微信转支付宝、微信转web、微信转RN

## Usage

Expand Down Expand Up @@ -31,12 +31,13 @@ proxy.navigateTo({

|参数名称|类型|含义|是否必填| 默认值 |备注|
|---|---|---|---|-------|---|
|platform|Object|各平台之间的转换|否| |使用 mpx 脚手架配置会自动进行转换,无需配置|
|exclude|Array(String)|跨平台时不需要转换的 api|-|
|~~platform~~|~~Object~~|~~各平台之间的转换~~|~~否~~| |已删除|
|~~exclude~~|~~Array(String)~~|~~跨平台时不需要转换的 api~~|已删除|
|usePromise|Boolean|是否将 api 转化为 promise 格式使用|否| false |-|
|whiteList|Array(String)|强行转化为 promise 格式的 api|否| [] |需要 usePromise 设为 true|
|blackList|Array(String)|强制不变成 promise 格式的 api|否| [] |-|
|fallbackMap|Object|对于不支持的API,允许配置一个映射表,接管不存在的API|否| {} |-|
|~~fallbackMap~~|~~Object~~|~~对于不支持的API,允许配置一个映射表,接管不存在的API~~|~~否~~| {} |已删除|
| custom | Object | 提供用户在各渠道下自定义api开放能力 | 否 | [] | - |

## example

Expand Down Expand Up @@ -65,6 +66,12 @@ mpx.showModal({

> 开启usePromise时所有的异步api将返回promise,但是小程序中存在一些异步api本身的返回值是具有意义的,如uploadFile会返回一个uploadTask对象用于后续监听上传进度或者取消上传,在对api进行promise化之后我们会将原始的返回值挂载到promise.__returned属性上,便于开发者访问使用

**⚠️ 注意**
- mpx中开启usePromise后,所有options中有success和fail都会以promise风格处理,不与微信拉齐
- 开启 usePromise 后,若同时写了 success 和 then,两者都会执行。但需注意:启用 usePromise 后,API 调用应使用 promise 方式;若仍用 success/fail 接收回调,当 API 调用失败时,promise 的 catch 会无法捕获错误,进而触发 onUnhandledRejection 来捕获该错误。
- 整体支持 promise 写法,但个别 API 若想继续用 success/fail 回调,又不想出现调用失败未被 catch 的报错,可在调用API方法时传 usePromise: false(默认 true),临时关闭本次 promise 转换


```js
import mpx from '@mpxjs/core'
import apiProxy from '@mpxjs/api-proxy'
Expand All @@ -82,4 +89,16 @@ mpx.showActionSheet({
.catch(err => {
console.log(err)
})

// 关闭本次调用转换promise风格
mpx.showActionSheet({
itemList: ['A', 'B', 'C'],
success (res) {
console.log(res.tapIndex)
},
fail () {
console.log(err)
},
usePromise: false // 关闭设置
})
```
38 changes: 12 additions & 26 deletions packages/api-proxy/src/common/js/promisify.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import { ENV_OBJ } from './utils'
import { ENV_OBJ, warn } from './utils'

// 特别指定的不进行Promise封装的方法
const blackList = [
'clearStorage',
'hideToast',
'hideLoading',
'drawCanvas',
'canIUse',
'stopRecord',
'pauseVoice',
'stopVoice',
'pauseBackgroundAudio',
'stopBackgroundAudio',
'showNavigationBarLoading',
'hideNavigationBarLoading',
'getPerformance',
'hideKeyboard',
'stopPullDownRefresh',
'pageScrollTo',
'reportAnalytics',
'getMenuButtonBoundingClientRect',
'reportMonitor',
'reportEvent',
'connectSocket',
'base64ToArrayBuffer',
'arrayBufferToBase64',
'getDeviceInfo',
Expand All @@ -33,16 +19,12 @@ const blackList = [
'postMessageToReferrerPage',
'postMessageToReferrerMiniProgram',
'reportPerformance',
'getPerformance',
'preDownloadSubpackage',
'router',
'nextTick',
'checkIsPictureInPictureActive',
'worklet',
'revokeBufferURL',
'reportEvent',
'getExptInfoSync',
'reserveChannelsLive',
'getNFCAdapter',
'isVKSupport'
]
Expand Down Expand Up @@ -79,18 +61,22 @@ function promisify (listObj, whiteList, customBlackList) {
if (typeof listObj[key] !== 'function') {
return
}

result[key] = function (...args) {
const obj = args[0] || {}
// 不需要转换 or 用户已定义回调,则不处理
if (!promisifyFilter(key)) {
return listObj[key].apply(ENV_OBJ, args)
} else { // 其他情况进行转换
if (!promisifyFilter(key)) {
result[key] = listObj[key].bind(ENV_OBJ)
} else {
result[key] = function (...args) {
const obj = args[0] || {}
if (obj.usePromise === false) {
return listObj[key].apply(ENV_OBJ, args)
}
if (!args[0]) args.unshift(obj)
let returned
const promise = new Promise((resolve, reject) => {
const originSuccess = obj.success
const originFail = obj.fail
if (originSuccess || originFail) {
warn(`The [${key}] method has been promisified, please use .then or .catch to handle the result, if you need to handle the result with options.success/fail, please set options.usePromise to false to close the promisify in this call temporarily. `)
}
obj.success = function (res) {
originSuccess && originSuccess.call(this, res)
resolve(res)
Expand Down
4 changes: 1 addition & 3 deletions packages/api-proxy/src/common/js/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { hasOwn, noop, getEnvObj, getFocusedNavigation, error as errorHandler, warn as warnHandler } from '@mpxjs/utils'
import { getCurrentInstance } from '@mpxjs/core'

/**
*
Expand Down Expand Up @@ -90,8 +89,7 @@ function failHandle (result, fail, complete) {
}

function getCurrentPageId () {
const currentInstance = getCurrentInstance()
const id = currentInstance?.proxy?.getPageId() || getFocusedNavigation()?.pageId || null
const id = getFocusedNavigation()?.pageId || null
return id
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const styles = StyleSheet.create({
bottom: 0,
right: 0,
position: 'absolute',
zIndex: 1000
zIndex: 10000
},
maskWrap: {
left: 0,
Expand Down Expand Up @@ -65,8 +65,8 @@ const styles = StyleSheet.create({
},
itemTextStyle: {
fontSize: 18,
height: 22,
lineHeight: 22
paddingTop: 2,
paddingBottom: 2
},
buttonStyle: {
paddingTop: 10,
Expand Down Expand Up @@ -195,8 +195,8 @@ function ActionSheet ({ itemColor, height, success, fail, complete, alertText, i
style={{
color: '#000000',
fontSize: 18,
lineHeight: 22,
height: 22,
paddingTop: 2,
paddingBottom: 2,
width: '100%',
textAlign: 'center'
}}
Expand Down
7 changes: 4 additions & 3 deletions packages/api-proxy/src/platform/api/image/Preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export default class Preview {
})
// click to close
bindTap(this.preview, () => {
this.currentIndex = 0
this.preview.style.display = 'none'
this.preview.querySelector('.__mpx_preview_images__').remove()
this.preview.remove()
Expand All @@ -54,17 +53,19 @@ export default class Preview {
* @param {string[]} options.urls - 图片地址数组
*/
show (options) {
const supported = ['urls', 'success', 'fail', 'complete']
const supported = ['urls', 'success', 'fail', 'complete', 'current']
Object.keys(options).forEach(key => !supported.includes(key) && warn(`previewImage: 暂不支持选项 ${key} !`))
const { urls, success, fail, complete } = options
const { urls, current, success, fail, complete } = options
try {
this.currentIndex = urls.indexOf(current) > -1 ? urls.indexOf(current) : 0
getRootElement().appendChild(this.preview)
this.preview.style.display = 'block'
// create images with urls
// append to preview
this.preview.appendChild(createDom('div', { class: '__mpx_preview_images__' }, urls.map(url => createDom('div', {
style: `background-image: url(${url})`
}))))
this.preview.querySelector('.__mpx_preview_images__').style.transform = `translateX(-${this.currentIndex * 100}%)`
this.maxIndex = urls.length
this.updateTextTip()
successHandle({ errMsg: 'previewImage:ok' }, success, complete)
Expand Down
3 changes: 2 additions & 1 deletion packages/api-proxy/src/platform/api/modal/rnModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ const showModal = function (options = {}) {
alignItems: 'center',
display: 'flex',
backgroundColor: 'rgba(0,0,0,0.6)',
position: 'absolute'
position: 'absolute',
zIndex: 10000
},
modalContent: {
paddingTop: 20,
Expand Down
2 changes: 1 addition & 1 deletion packages/api-proxy/src/platform/api/route/index.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function isLock (navigationHelper, type, options) {
navigationHelper.lastFailCallback('timeout')
navigationHelper.lastFailCallback = null
}
}, 350)
}, 1000)
return false
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useState, useCallback, forwardRef, ForwardedRef, useImperativeHandle, ReactNode, ReactElement } from 'react'
import { View, StyleSheet } from 'react-native'
import { useState, useCallback, forwardRef, ForwardedRef, useImperativeHandle, ReactNode, ReactElement, Fragment } from 'react'

export type State = {
portals: Array<{
Expand Down Expand Up @@ -48,13 +47,10 @@ const _PortalManager = forwardRef((props: PortalManagerProps, ref:ForwardedRef<u

return (
<>
{state.portals.map(({ key, children }, i) => (
<View
key={key}
collapsable={false} // Need collapsable=false here to clip the elevations
style={[StyleSheet.absoluteFill, { zIndex: 1000 + i, pointerEvents: 'box-none' }]}>
{state.portals.map(({ key, children }) => (
<Fragment key={key}>
{children}
</View>
</Fragment>
))}
</>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const styles = StyleSheet.create({
borderRadius: 10
}
})

const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((props, ref): JSX.Element | null => {
const { src, bindmessage, bindload, binderror } = props
const mpx = global.__mpx
Expand Down Expand Up @@ -126,10 +127,27 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
style: defaultWebViewStyle
})

const hostValidate = (url: string) => {
const host = url && new URL(url).host
const hostWhitelists = mpx.config.rnConfig?.webviewConfig?.hostWhitelists || []
if (hostWhitelists.length) {
return hostWhitelists.some((item: string) => {
return host.endsWith(item)
})
} else {
return true
}
}

if (!src) {
return null
}

if (!hostValidate(src)) {
console.error('访问页面域名不符合domainWhiteLists白名单配置,请确认是否正确配置该域名白名单')
return null
}

const _reload = function () {
if (__mpx_mode__ !== 'ios') {
fristLoaded.current = false // 安卓需要重新设置
Expand Down Expand Up @@ -182,6 +200,9 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
}
}
const _message = function (res: WebViewMessageEvent) {
if (!hostValidate(res.nativeEvent?.url)) {
return
}
let data: MessageData = {}
let asyncCallback
const navObj = promisify({ redirectTo, navigateTo, navigateBack, reLaunch, switchTab })
Expand Down Expand Up @@ -232,7 +253,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
break
default:
if (type) {
const implement = mpx.config.webviewConfig.apiImplementations && mpx.config.webviewConfig.apiImplementations[type]
const implement = mpx.config.rnConfig.webviewConfig && mpx.config.rnConfig.webviewConfig.apiImplementations && mpx.config.rnConfig.webviewConfig.apiImplementations[type]
if (isFunction(implement)) {
asyncCallback = Promise.resolve(implement(...params))
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default {
case 'postMessage':
let data = {
type: 'message',
data: params[0]?.data
data: params[0]?.data || params[0] // 补充兜底逻辑
}
this.$emit(eventMessage, getCustomEvent(eventMessage, data, this))
asyncCallback = Promise.resolve({
Expand All @@ -148,7 +148,7 @@ export default {
break
default:
if (type) {
const implement = mpx.config.webviewConfig.apiImplementations && mpx.config.webviewConfig.apiImplementations[type]
const implement = mpx.config.webConfig?.webviewConfig?.apiImplementations?.[type]
if (isFunction(implement)) {
asyncCallback = Promise.resolve(implement(...params))
} else {
Expand All @@ -174,7 +174,7 @@ export default {
})
},
hostValidate (host) {
const hostWhitelists = mpx.config.webviewConfig && mpx.config.webviewConfig.hostWhitelists || []
const hostWhitelists = mpx.config.webConfig?.webviewConfig?.hostWhitelists || []
if (hostWhitelists.length) {
return hostWhitelists.some((item) => {
return host.endsWith(item)
Expand Down