最近在公司在做关于CRN的发布流程工具,其中不免涉及到发布状态的轮询,因此在这里记录了实现方式,主要涉及页面打开隐藏控制轮询的开启与关闭。此外还需要注意,若上一次请求未得到及时响应的话,需要等待上一次请求完成后再发送下一个请求,主要为防止网络请求过慢造成后续请求集体阻塞。
轮询创建
创建一个接受执行轮询操作的方法和轮询时间间隔:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| export const createRefresher = (f, delay) => { let timer = null; const start = () => { if (timer === undefined) { timer = setInterval(f, delay); } else { clearInterval(timer); timer = undefined; timer = setInterval(f, delay); } };
const stop = () => { if (timer) { clearInterval(timer); timer = undefined; } };
return { start, stop }; }
|
在类组件的构造方法中创建轮询
1 2 3 4 5 6 7
| export default class PackagePublishDetail extends Component { static contextType = CommonContext; constructor() { this.refresher = createRefresher(this.queryPublishStatus, 3000); } }
|
开启与关闭
1 2 3 4 5
| this.refresher.start()
this.refresher.stop()
|
页面显隐控制轮询
为了节省开销,我们不可能每时每刻处于长轮询状态,尤其是多人发布时,很可能会导致服务器压力过大而崩溃。当用户打开页面查看并操作时,需要了解发布状态进入哪个环节,这时需要轮询状态,否则需要关闭轮询。
绑定和解绑visibilitychange
事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| componentWillUnmount() { document.removeEventListener('visibilitychange', this.handleVisibilitychange); this.refresher.stop(); }
componentDidMount() { document.addEventListener('visibilitychange', this.handleVisibilitychange); }
handleVisibilitychange = () => { if (document.hidden) { this.refresher.stop(); } else { this.queryPublishStatus(); } };
|
进一步优化
对上述的handleVisibilitychange
方法前加入轮询完成标志。
1 2 3 4 5 6 7 8
| handleVisibilitychange = () => { if (document.hidden) { this.refresher.stop(); } else { this.allBack() && this.queryPublishStatus(); } };
|