zoukankan      html  css  js  c++  java
  • Axios中的取消请求源码解析

    前言

    在开发中,为了活动动态数据,因此我们需要与后台通过请求进行交互,获取动态数据来展现给用户看。有些一些网站对实时信息要求还更高,比如股票类、聊天类、直播类等。本章内容涉及思想层面东西比较多,如果出现知识盲点无所谓,主要就是体会Promise的运用思想!思想!思想!(小白也可以试试)

    当下流行的http库

    http库在当下作为请求交互来说,是比较主流的,今天就给大家介绍一个比较受欢迎的库:Axios

    它在github上的star数截至到2020年3月已经达到70.2k,这算是比较多的了

    今天讲什么

    由于Axios是基于Promise的,有些操作如果更多的触碰到底层promise,代码上不免会让大家比较蒙,本文主要不是为了科普Axios的基本代码(因为官网上中文的、英文的多了去了)。

    今天就给大家说一下,比较难懂的代码:cancelToken,他是怎么利用Promise跑起来的以及一些设计思路,不管你会不会这个库,都可以尝试理解一下源码的设计思路。

    取消请求

    先说一下,有时我们上传一个文件到服务器的时候,文件很大,不可能一下传完,但是我们中途发现文件错了,因此我们点击取消,即为:取消请求。

    在Axios中的代码如下:

    // 创建取消令牌的生成器对象
    const CancelToken = axios.CancelToken;
    // 从中获取令牌对象
    const source = CancelToken.source();
    // 发请求
    axios.get('/user/12345', {
      // 传递令牌
      cancelToken: source.token
    });
    // 2秒取消请求
    setTimeout(function () { 
    	source.cancel();
    },2000);
    

    虽然注释已经打上了,中文意思大家都懂,但是很少有人能知道这其中Promise做了啥,而相反我们更容易理解为cancel函数中断了异步请求,是中断了Promise吗? 不是!

    源码实现

    接下来我带大家简单实现一个,你可能就清楚了。

    为了便于理解,我少封装了一层,针对上述 const source = CancelToken.source();

    我写了如下代码,看起来差不多

    var source = source();
    

    接着模拟axios.get(url,options); 函数,我也简单的这么写

    axios_get('url',{
        cancelToken:source.token
    });
    

    最后我们做定时器

    setTimeout(function () {
    			source.cancel(); // 5秒之后执行下一步操作
    },5000)
    

    好了,需要调用的代码都写好了,接下来就是就是实现这些函数,首先我应该有个source函数,他返回一个对象,可以调用cancel函数,有个token属性

    function source () {
        return {
            token:'??'
            cancel:'??'
        }
    }
    

    ok,接下来我们还有axios_get函数,他的作用就是发请求,假设我们使用XMLHttpRequest对象,他里面则最终经过配置后需要发请求。

    function axios_get(url,options) {
        // 先各种配置
        
        // 最终发请求 
        xhr.request();
    }
    

    以上代码这个思路没问题吧?
    接着来!用户点击后,通过调用source.cancel() 实际需要访问到axios_get内部的XMLHttpRequest对象,调用其的abort函数才能真正意义的取消。因此,我们要想办法让source某一部分能访问到该对象。这里唯一的触及点就是传递的cancelToken:source.token。

    function axios_get(url,options) {
        // 先各种配置
        if (options.cancelToken) {
            // ...  xhr.abort();
        }
        // 最终发请求   
         xhr.request();
    }
    

    这里你可以想到直接调用函数,或者回传xhr.abort等方式,但是由于axios是基于Promise的,因此,我们最好用Promise来处理,显得也会更优雅,我们假设这个cancelToken就是Promise,那么给他定义.then的话,中间就只差一个resolve(),该函数就能得到执行了

    function axios_get(url,options) {
        // 先各种配置
        if (options.cancelToken) {
            options.cancelToken.then(function () {
               xhr.abort(); 
            });
        }
        // 最终发请求  
        xhr.request();
    }
    

    好了,继续往上追溯,这里的cancelToken也就是我们source.token,他要是个Promise的话,我们就得回到之前的创建source函数中

    function source () {
        let p = new Promise(function (resolve,reject) {
    		// 这里几乎啥也不做
        });
        return {
            token:p,
            cancel:'??'
        }
    }
    

    好像还有点不对,我们应该把链接Promise和then的一个放行开关传递出去,这样才能调用resolve执行后续的.then从而执行取消请求的代码

    function source () {
        let cancel;
        let p = new Promise(function (resolve,reject) {
    		cancel = resolve;
        });
        return {
            token:p,
            cancel:cancel
        }
    }
    

    好了,至此,我们在source里面创建Promise,将其本身和resolve(cancel) 向外导出,在请求的时候传递给axios_get函数,其内部配置promise的.then:取消请求。

    file
    如图就是这个思想,主要就是我们利用了Promise 和 其 resolve 来放行到下一步,进行延迟执行。

    完整代码:

    	// 创建Promise,返回放行开关cancel
    		function source () {
    			var cancel;
    			var promise = new Promise(function (resolve) {
    				cancel = resolve;
    			});
    			return {
    				cancel:cancel,
    				token:promise 
    			}
    		}
    	// 发请求
    		function axios_get(config) {
    			if (config.cancelToken) {
    				config.cancelToken.then(function () {
    					xhr.abort();
    				})
    			}
    		}
    
    // 代码执行
    		var source = source();
    
    		axios_get({cancelToken:source.token});
    
    		setTimeout(function () {
    			source.cancel(); // 5秒之后执行下一步操作
    		},5000)
    
  • 相关阅读:
    JS制作图表
    把图片存入数据库
    .NET各种小问题
    JS各种小问题
    JS操作cookie
    JS处理Json数据
    git与svn的区别
    关于java中的一些循环
    java基础面试(上)
    Spring事务
  • 原文地址:https://www.cnblogs.com/qidaoxueyuan/p/12396955.html
Copyright © 2011-2022 走看看