浅谈中断在异步事件中的作用

在日常开发中,我们经常会用到ajax与后台进行数据交互,异步请求的情况一般分为两种,小量数据下的一次性请求与大量数据下的连续或并发请求,这篇文章介绍的就是中断在大量连续请求的情况下的作用和必要性。
我们先设想一个情况,比如我要画出一个传感器最近一个月的监测数据的统计图,如果我采用一次性获取所有的数据,如果传感器的采集周期较短,那么一个月的时间长度将会有一个非常巨大的的数据量,采用一次获取的情况将会使得用户的等待时间非常漫长,所以我们就会在知道数据长度的情况下使用并发请求,在不知道数据长度的情况下使用连续的请求来获取数据,然后在本地合并获取到的数据并绘图,这样,用户只需要等一个请求的时间就可以看到统计图了。用户看到图后非常满意,然后点击了下一个传感器,程序就会重新执行上面的方法。这个过程看起来很好也没什么错对吧?其实,这样处理有可能会造成比较严重的错误,那就是数据污染。
《浅谈中断在异步事件中的作用》

这是我们整个数据处理的流程图,有一点需要注意的是从开始发出的三条线是异步的方法,不在主进程中。当第一个请求完成后,第二个或者其他的请求并没有完成。这时用户点击了新的传感器,我们又会发送一系列的请求到服务器。这时我们的客户端就会收到上一个传感器的数据和新的传感器的数据。然而系统并不能判断这次收到的数据是上一轮的还是这一轮的,都会让这些数据走正常的方法然后展示出来,这样,新旧数据就混在了一起。
解决这个问题的思路很简单,那就是在发行请求前,关闭掉之前发送的所有请求,这样,新的数据就不会被旧的数据所污染。所幸,我们使用比较广的两种ajax插件都有这样的方法,下面就以我比较喜欢的axios为例。

    ///假设传感器的数据有20页,每页100条
    import axios from 'axios'; 
    let CancelToken = axios.CancelToken;
    let cancel;
    function loop(id){///这种请求一般是连续循环的请求
        axios.get({
            url: '/api/fakePath/',
            params: {
                id
            },
            cancelToken: new CancelToken(function executor(c) {///这个函数会传递一个取消的函数进来,这里用cancel来接收
                cancel = c;
            })
        })
    }
    /// 使用方法: cancel()
    
    let source = CancelToken.source();
    function concurrence(arr){///这种是并发多个请求来获取数据
        for(let i in arr){
            axios.get({
                url: '/api/fakePath/',
                params: {
                    id:i
                },
                cancelToken: source.token
            })
        }
    }
    
    
   ///使用方法,这种可以传一个message作为提示: source.cancel('Operation canceled by the user.');

这样在我们就创建了一系列的异步请求,并且获取或者赋予了取消函数。loop函数因为是连续的请求,一次只有一个,所以使用了新建CancelToken,而并发的情况下,则采用公用一个CancelToken。这样只要在新请求发起前,调用对应的CancelToken函数,就可以完美解决数据污染的问题了

    原文作者:御坂御坂
    原文地址: https://segmentfault.com/a/1190000015667004
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞