• 关于我对axios的源码理解


    1.创建构造函数

    原始构造函数用于存储默认属性与拦截器操作

    拦截器管理器构造函数InterceptorManager 主要是为了存储拦截器的失败与成功操作函数

    1. function Axios(config) {
    2. // 数据初始化
    3. this.defaults = config // 默认属性
    4. this.intercepters = { // 拦截器操作
    5. request: new InterceptorManager(), // 用于请求前拦截
    6. response: new InterceptorManager(), // 用于响应结果拦截
    7. }
    8. }

    2.创建Axios构造函数的原型方法(get,post,request)

    重点是request函数,主要是用promise来进行链式操作

    创造promise

    chain存储axios请求函数dispatchRequest,undefined(失败占位符)

    请求拦截在头部插入

    响应拦截在尾部插入

    真实axios请求在(请求拦截)与(响应拦截)之间

    先执行请求拦截再执行真是axios请求,最后执行响应拦截

    while 保证全部执行

    1. // 创建原型方法
    2. Axios.prototype.get = function (config) {
    3. return this.request({ ...config, method: 'GET', })
    4. }
    5. Axios.prototype.post = function (config) {
    6. return this.request({ ...config, method: 'POST' })
    7. }
    8. Axios.prototype.request = function (config) {
    9. console.log('发送 AJAX 请求 请求的类型为 ' + config.method);
    10. // 发送请求
    11. // 创建promise对象
    12. let promise = Promise.resolve(config);
    13. //发送请求
    14. let chain = [dispatchRequest, undefined];//undefined进行占位
    15. // 请求拦截
    16. this.intercepters.request.handlers.forEach(item => {
    17. //头部插入,后写入的先执行
    18. chain.unshift(item.fulfilled, item.injected)
    19. })
    20. // debugger
    21. //响应拦截器
    22. this.intercepters.response.handlers.forEach(item => {
    23. //尾部插入,后写入的后执行
    24. chain.push(item.fulfilled, item.rejected);
    25. });
    26. //遍历
    27. while (chain.length > 0) {
    28. //保证全部执行,成功函数,失败函数
    29. promise = promise.then(chain.shift(), chain.shift());
    30. }
    31. return promise;
    32. }

    3.创建dispatchRequest 函数

    1. function dispatchRequest(config) {
    2. return xhrRequest(config).then(response => {
    3. //响应的结果进行转换处理
    4. //....
    5. return response;
    6. }, error => {
    7. throw error;
    8. });
    9. }

    4. xhrRequest发送请求

    promise进行xhr请求

    当存在cancelToken的时候进行取消操作

    promise.then的执行时机是在cancel方法改变promise状态才执行

    1. function xhrRequest(config) {
    2. return new Promise((reslove, inject) => {
    3. let xhr = new XMLHttpRequest();
    4. xhr.open(config.method, config.url)
    5. xhr.send();
    6. xhr.onreadystatechange = function () {
    7. if (xhr.readyState == 4) {
    8. if (xhr.status == 200 && xhr.status < 300) {
    9. reslove({
    10. config: config,
    11. data: xhr.response,
    12. Headers: xhr.getAllResponseHeaders(),
    13. request: xhr,
    14. status: xhr.status,
    15. statusText: xhr.statusText
    16. })
    17. } else {
    18. inject(new Error('请求失败 失败的状态码为' + xhr.status))
    19. }
    20. }
    21. }
    22. //关于取消请求的处理
    23. if (config.cancelToken) {
    24. //对 cancelToken 对象身上的 promise 对象指定成功的回调
    25. config.cancelToken.promise.then(value => {
    26. xhr.abort();
    27. console.log('请求已经被取消')
    28. //将整体结果设置为失败
    29. inject(new Error('请求已经被取消'))
    30. });
    31. }
    32. })
    33. }

    6.拦截器管理器构造函数

    1. function InterceptorManager() {
    2. this.handlers = [];
    3. }
    4. InterceptorManager.prototype.use = function (fulfilled, rejected) {
    5. this.handlers.push({
    6. fulfilled,
    7. rejected
    8. })
    9. }

    7.创建axios声明函数,生成axios,并将Axios的原型方法跟默认属性添加到axios上

    1. function createInstance(config) {
    2. // 实例化一个对象 , bind绑定this而不执行
    3. let context = new Axios(config)
    4. let instance = Axios.prototype.request.bind(context);
    5. // console.log(instance)
    6. // 将context的原型方法添加到instance上
    7. Object.keys(Axios.prototype).forEach(key => {
    8. instance[key] = Axios.prototype[key].bind(context)
    9. })
    10. // 将context中的default 与intercepters添加到instance上
    11. Object.keys(context).forEach(key => {
    12. instance[key] = context[key]
    13. })
    14. // console.dir(instance)
    15. return instance;
    16. }

    8.绑定拦截器事件

    1. axios.intercepters.request.use(function one(config) {
    2. console.log('请求拦截器 成功 - 1号');
    3. return config;
    4. }, function one(error) {
    5. console.log('请求拦截器 失败 - 1号');
    6. return Promise.reject(error);
    7. });
    8. axios.intercepters.request.use(function two(config) {
    9. console.log('请求拦截器 成功 - 2号');
    10. return config;
    11. }, function two(error) {
    12. console.log('请求拦截器 失败 - 2号');
    13. return Promise.reject(error);
    14. });
    15. // 设置响应拦截器
    16. axios.intercepters.response.use(function (response) {
    17. console.log('响应拦截器 成功 1号');
    18. return response;
    19. }, function (error) {
    20. console.log('响应拦截器 失败 1号')
    21. return Promise.reject(error);
    22. });
    23. axios.intercepters.response.use(function (response) {
    24. console.log('响应拦截器 成功 2号')
    25. return response;
    26. }, function (error) {
    27. console.log('响应拦截器 失败 2号')
    28. return Promise.reject(error);
    29. });

    9. CancelToken 构造函数用来取消请求

    创造promise,先不执行resolve成功函数,而是将resolve存储起来,将function(){resolvePromise();}作为参数传递给cancel

    1. function CancelToken(executor){
    2. //声明一个变量
    3. var resolvePromise;
    4. //为实例对象添加属性
    5. this.promise = new Promise((resolve) => {
    6. //将 resolve 赋值给 resolvePromise
    7. resolvePromise = resolve
    8. });
    9. console.log(this.promise,'this.promise')
    10. //调用 executor 函数
    11. executor(function(){
    12. //执行 resolvePromise 函数
    13. resolvePromise();
    14. });
    15. }

    使用 

    1. "en">
    2. <head>
    3. "UTF-8">
    4. "viewport" content="width=device-width, initial-scale=1">
    5. <link href="css/style.css" rel="stylesheet">
    6. "container">
    7. "page-header">axios取消请求

  • 相关阅读:
    (附源码)node.js自我展示博客网站 毕业设计 231547
    小白必看:测试人有必要参考的软件测试工作规范
    版本控制--Git
    爬虫抓取数据超时是什么原因?如何解决爬虫抓取数据超时问题?
    【小程序】微信公众号模板消息跳转小程序发送失败:errcode=40013 , errmsg=invalid appid rid:...
    java基于 ssm+jsp的线上授课作业管理系统
    【C++修炼之路】6. 内存管理
    web结课作业的源码——HTML+CSS+JavaScript仿oppo官网手机商城(1页)
    TypeScript 面向对象
    LeetCode 0799. 香槟塔
  • 原文地址:https://blog.csdn.net/beichen3997/article/details/127994840