代码分析
最近在和别的团队合作一个项目。看了别人的代码,感触特别多。代码写的特别优雅。
// flexbridge.js
const FlexBridge = class {
constructor(){
//桥接具体实现(自动依赖注入)
this.bridge = null
// 前端的枚举类型
this.IOS = "ios"
this.ANDROID = "android"
this.UNKNOWN = "unknown"
this.APP = "app"
this.H5 = "h5"
this.WEIXIN = "weixin"
this.WXXCX = "wxxcx"
this.QQ = "qq"
//全局暴露,给静态页面使用
window["FlexBridge"] = this
}
async _(method, args){
if(this.bridge === null){
let client = await this.getClientInfo().type
let bridgeModule = null
switch (client) {
// 实现按需加载 根据不同的端 加载对应的实现类
case this.APP:
bridgeModule = import( /* webpackChunkName: "bridge-app" */ './bridges/app.js')
break;
case this.H5:
bridgeModule = import( /* webpackChunkName: "bridge-h5" */ './bridges/h5.js')
break;
case this.WXXCX:
case this.WEIXIN:
bridgeModule = import( /* webpackChunkName: "bridge-weixin" */ './bridges/weixin.js')
break;
default:
throw new Error('Unknown Client')
break;
}
}
bridgeModule = await bridgeModule
// 实例化 具体的桥接
this.bridge = new bridgeModule.default(this)
// 返回一个promise
return new Promise((resolve, reject) =>{
// 如果桥接中有该方法
if(method in this.bridge)
// 把resolve、reject作为入参,和args一起传给bridge的method
this.bridge[method].call(this.bridge, args, resolve, reject)
// 如果没有 则抛出异常
else
reject({
code: 99,
message: `${method}尚未实现`
})
})
}
// 获取系统信息
getOSInfo(){
let ua = navigator.userAgent
let type = this.UNKNOWN
if (/Android|Adr\s|Linux\sU|U\sLinux/i.test(ua))
type = this.ANDROID
else if (/iPh(one)?\sOS|iOS/i.test(ua))
type = this.IOS
let info = {
type: type,
version: "" //todo...
}
// 1. 返回立即执行函数
// 2. 给getOSInfo方法重新赋值为 info
// 3. 使用闭包 第二次调用就不用再次执行正则的判断了
return (this.getOSInfo = () => info)()
}
// 获取端信息
getClientInfo(){
let ua = navigator.userAgent
let type = this.H5
if(/xxx/i.test(ua)) {
type = this.APP
}
else if(/MicroMessenger/i.test(ua)) {
let res = null
try {
res = await wx.miniProgram.getEnv()
if(res && res.miniprogram) {
type = this.WXXCX
}
else {
type = this.WEIXIN
}
} catch (e) {
type = this.WEIXIN
}
}
else if (/QQ\//i.test(ua)) {
type = this.QQ
}
let info = {
type,
version: "预留字段"
}
return (this.getClientInfo = ()=> Promise.resolve(info))()
}
// 获取定位信息
getLocation() { return this._('getLocation', arguments) }
}
export default new FlexBridge()
// main.js
import FlexBridge from "flex-bridge"
Vue.prototype.bridge = FlexBridge
// xxx.vue 用户页面中调用
this.bridge.getLocation({
needAddress: 1,
needPoi: 1,
radius: 1000
}).then(data => {
console.log(data);
}).catch(error => {
console.log(error);
})
// h5.js
class H5 = class {
constructor(flexbridge) {
this.flexbridge = flexbridge
}
getLocation(args, resolve, reject) {
if('geolocation' in navigator){
let { needAddress, needPoi, radius, bizType, uuid } = args[0]
navigator.geolocation.getCurrentPosition(data => {
let lat = data.coords.latitude
let lng = data.coords.longitude
let coordType = 'wgs84'
if(needAddress === 1){
// xxx
}
else{
resolve({lat, lng, coordType})
}
}, error => {
if(error.code == error.TIMEOUT){
this.getLocation({
enableHighAcuracy: false,
timeout: 4e3,
retryed: true
}, resolve, reject)
}
else{
reject({
code: 'xx',
exception: error
})
}
})
}
else{
reject({
code: 'xx',
message: 'Not support geolocation'
})
}
}
}
export default H5