标题实在不知道怎么写了,感觉怎么写都有点不太准确。简单描述下场景。

比如在hybrid开发时,使用JsBridge提供操作给js,如果提供的操作需要在web页面加载完立即调用(如埋点日志之类的),可能调用失败,即使是在window.onload里调用也未必能获取到,而系统又没有提供准确的监听事件来判断,所以通常的做法可能会是这样的:

1
2
3
setTimeout(() => {
// TODO 调用jsBridge提供的方法
}, 600)

延迟一小段时间再去执行,这种方法虽然可行,但总觉得很蛋疼。因为虽然JsBridge不会立即加载完成,但不同的系统下或由于缓存的情况下,加载时间各不相同。

为了能较为准确的检测到其是否加载完成,也只好勉为其难的使用定时器去不停地检测。

1
2
3
4
5
6
7
let timer = setInterval(() => {
// 判断方法是否存在
if (typeof window.jsBridgeAction === 'function') {
clearInterval(timer)
// TODO 做该做的事
}
}, 50)

也还好,在此提供一种封装方法,用起来跟onload事件监听似的,皆大欢喜。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const readyPromise = (variableName, {
rate = 50,
timeout = 1500
} = {}) => {
if (typeof variableName !== 'string') {
throw new Error('The first argument should be a string')
}

let rateTimer, overTimer

const _GLOBAL = new Function('return this')()

const _clearTimer = () => {
clearInterval(rateTimer)
clearTimeout(overTimer)
}

return new Promise((resolve, reject) => {
if (_GLOBAL[variableName]) {
resolve()
return
}

rateTimer = setInterval(() => {
if (_GLOBAL[variableName]) {
_clearTimer()
resolve()
}
}, rate)

overTimer = setTimeout(() => {
_clearTimer()
reject(new Error('timeout'))
}, timeout)
})
}

readyPromise('jsBridgeAction').then(() => {
// TODO
}).catch(e => {
console.error(e)
})

也可以直接使用ready-promise库,使用方法稍有不同:

1
2
3
4
5
6
7
8
npm i ready-promise -S
``

```javascript
import readyPromise from 'ready-promise'
readyPromise(() => {
return typeof window.jsBridgeAction === 'function'
}).then(() => {}).catch(e => {})