• Axios源码阅读笔记#1 默认配置项


    Promise based HTTP client for the browser and node.js

    这是 Axios 的定义,Axios 是基于 Promise,用于HTTP客户端——浏览器和 node.js 的库 。Github:https://github.com/mzabriskie/axios

    官方文档中 Axios 的 feature 有:

      1)浏览器中使用 XMLHttpRequest;

      2)node.js 中使用 http 请求;

      3)支持 Promise API;

      4)能够拦截请求与响应;

      5)能够转换请求与响应的数据;

      6)请求能够取消;

      7)自动转换 JSON 数据;

      8)客户端支持防范 XSRF;

    记得有一次面试中,面试官问到,Axios 是用什么实现的,我回答说 Ajax。看面试官的表情,他似乎认为这个答案是错的。后来仔细想了一下,Axios 是用 Ajax 实现异步请求的, 而异步操作则是基于 Promise 的。而 Axios 的目的呢,就是为了在浏览器和 node.js 中,以统一、简洁的方式使用 Ajax、处理回调。简单的说,就是用 Promise 包装了一下 AJAX(当然并没有这么简单)。

    最简单的使用方法,仅仅需要向 Axios 传递请求地址,便可以发送一个 GET 请求。Ajax 中其它的配置 Axios 都已经默认设置好了。当然也可以根据需求传入 config,覆盖默认配置项。默认配置定义在 /lib/defaults.js 中。

    axios(url[, config])

    default

    var defaults = {
      adapter: getDefaultAdapter(),
    
      transformRequest: [...],
    
      transformResponse: [...],
    
      timeout: 0,          // 请求超时时间
    
      xsrfCookieName: 'XSRF-TOKEN',          // 用于获取 cookie 中 'XSRF-TOKEN' 的值
      xsrfHeaderName: 'X-XSRF-TOKEN',        // 用于设置请求头部
    
      maxContentLength: -1,
    
      validateStatus: function validateStatus(status) {
        return status >= 200 && status < 300;
      }
    };
    
    defaults.headers = {
      common: {
        'Accept': 'application/json, text/plain, */*'
      }
    };
    
    utils.forEach(['delete', 'get', 'head'], function forEachMehtodNoData(method) {
      defaults.headers[method] = {};
    });
    
    utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
      defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
    });
    
    module.exports = defaults;

    adapter

    浏览器和 node.js 实现异步请求的方式并不一样,那么 Axios 如何实现统一呢?

    function getDefaultAdapter() {
      var adapter;
      if (typeof XMLHttpRequest !== 'undefined') {
        // For browsers use XHR adapter
        adapter = require('./adapters/xhr');
      } else if (typeof process !== 'undefined') {
        // For node use HTTP adapter
        adapter = require('./adapters/http');
      }
      return adapter;
    }

    var defaults = {
      adapter: getDefaultAdapter(),

      ...

    }

    
    

    module.exports = defaults;

     

    在 defaults.js 中,通过分支选择判断,若 XMLHttpRequest 存在,代表当前环境为浏览器, 则异步请求将使用 XHR;否则,若存在 process,代表当前环境为 node.js,则使用 HTTP。

    Axios 基于 Promise 就体现在 adapter。无论是 XHR 还是 HTTP,都是经过 Promise 包装的,getDefaultAdapter() 返回的都是一个 Promise 对象。如果希望使用 fetch 或者其他自定义,在 config 中传入 adapter 就可以了,参考 gthub 的 /lib/adapters/README.md 的示例, adapter 应该是一个 Promise 对象。

    XHR

    在浏览器中 Axios 使用的是 XMLHttpRequest。我们通常会将 Ajax 等同于 XMLHttpRequest,但两者并不一样。《JavaScript 高级程序设计》中提到,“Ajax 技术的核心是 XMLHttpRequest 对象(简称XHR)”。在 xhr.js 中,主要是对 XHR请求以及响应数据的一些封装,使它能够兼容 IE8/9。

    上文提到客户端支持 XSRF防范  ,是在 xhr.js 中实现。往请求头中插入‘X-XSRF-TOKEN’字段。

        // Add xsrf header
        // This is only done if running in a standard browser environment.
        // Specifically not if we're in a web worker, or react-native.
        if (utils.isStandardBrowserEnv()) {
          var cookies = require('./../helpers/cookies');
    
          // Add xsrf header
          var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?
              cookies.read(config.xsrfCookieName) :
              undefined;
    
          if (xsrfValue) {
         // 默认配置中 xsrfHeadeName: 'X-XSRF-TOKEN' requestHeaders[config.xsrfHeaderName]
    = xsrfValue; } }

    transformRequest

    transformRequest 是根据请求数据的类型对数据进行转换,并改变 Content-Type。默认的  Content-Type 为 ‘application/x-www-form-urlencoded’
    transformRequest: [function transformRequest(data, headers) {
        normalizeHeaderName(headers, 'Content-Type');
        if (utils.isFormData(data) ||
          utils.isArrayBuffer(data) ||
          utils.isStream(data) ||
          utils.isFile(data) ||
          utils.isBlob(data)
        ) {
          return data;
        }
        if (utils.isArrayBufferView(data)) {
          return data.buffer;
        }
        if (utils.isURLSearchParams(data)) {
          setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
          return data.toString();
        }
        if (utils.isObject(data)) {
          setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
          return JSON.stringify(data);
        }
        return data;
      }],
    transformResponse
    transformResponse 默认将响应数据转换为 JSON格式。
    transformResponse: [function transformResponse(data) {
        /*eslint no-param-reassign:0*/
        if (typeof data === 'string') {
        // var PROTECTION_PREFIX = /^)]}',? /; data
    = data.replace(PROTECTION_PREFIX, ''); try { data = JSON.parse(data); } catch (e) { /* Ignore */ } } return data; }],
    了解 Axios 的默认配置项之后,就明白如何通过 config 来自定义请求了。
  • 相关阅读:
    戴德金分割第6页
    自己总结的学习方法
    自己总结的选股方法和建仓方法
    自编通达信公式集合
    电脑目录设置
    1·0天内跳空缺口的公式
    springsecurity
    java开发 日志框架选择
    javaFramwork title
    idea git忽略文件
  • 原文地址:https://www.cnblogs.com/xxhuan/p/7565567.html
Copyright © 2020-2023  润新知