React 监听页面是否切出,避免多余请求

5,241 阅读1分钟

不知道你是不是跟我一样,遇到过下面这种情况:

页面需要定时发送请求,获取数据,而且这个请求是一个公共请求,应用中所有页面都会进行这样一个操作。所以假如用户打开五个页面,那五个页面都会发送请求,即便用户看不到其余的4个。这种多余的请求会加重服务端的压力。

浏览器里在当前标签页切换时,会触发 visibilitychange 事件,我们可以通过监听这个事件来解决我们的问题。

class AgentList extends React.Component {
    constructor(props) {
        super(props);
        this.state= {
            list: []
        }
        this.refresher = this.createRefresher(this.getNotice, 30 * 1000);
    }
    
    componentDidMount() {
        window.setTimeout(() => {
          this.getNotice();
        }, 6000);

        document.addEventListener('visibilitychange', this.handleVisibilitychange);
    }
    
    componentWillUnmount() {
        this.refresher.stop();
        document.removeEventListener('visibilitychange', this.handleVisibilitychange);
    }
    
    getNotice = async () => {
        if (!document.hidden) {
          this.refresher.start();
        }
    
        const { data } = await API.getNotice();
        if (data && data.status === '1') {
            const { list } = data;
            this.setState({ popupList });
        }
    }
    
    handleVisibilitychange = () => {
        if (document.hidden) {
            this.refresher.stop();
        } else {
            window.setTimeout(() => {
                this.getNotice();
            }, 6000);
        }
    });
    
    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 };
    }
    
    render () {
        const { list } = this.state;
        return (
            <ul>
                list.map(item => <li>item</li>)
            </ul>
        )
    }
}

页面中不是必要的请求,可以延迟发送,尽量减少页面进入时同时发送的请求:

window.setTimeout(() => {
    this.getNotice();
}, 6000);

监听 visibilitychange 事件,当页面切出时,清除定时器;当页面切入时,重新发送请求,并在 getNotice() 当中判断如果页面在展示中,则开启定时器。

handleVisibilitychange = () => {
    if (document.hidden) {
        this.refresher.stop();
    } else {
        window.setTimeout(() => {
            this.getNotice();
        }, 6000);
    }
});

在这记录下,如果有错误的地方,欢迎大家批评之争,哈哈哈哈