Ajax基础

AJAX

Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

什么是 AJAX

  • 异步的 JavaScript 和 XML
  • 通过 AJAX,我们可以在不刷新整个页面的前提下,从后端请求数据,实现页面局部的内容刷新(传统网页要更新内容必须重载整个页面)。

AJAX 工作原理

1、在某个阶段触发一个事件,然后浏览器创建一个 XMLHttpRequest 对象,向服务器发送一个请求信息;
2、服务器根据请求的信息作出响应,返回页面所需要的内容;
3、浏览器使用请求到的数据通过 JS 处理实现网页的更新。

AJAX 请求过程

  • 创建 XMLHttpRequest 对象
let xhr;
if (window.XMLHttpRequest) {
  xhr = new XMLHttpRequest()
} else {
  xhr = new ActiveXObject('Microsolf.XMLHTTP')
}
  • 发送请求

    • GET
    /**
     * type -- 类型
     * url -- 请求地址
     * async -- 是否异步发起请求
     */
    xhr.open(type, url, async)
    
    
    • POST
    /**
     * POST 请求比 GET 请求多一步,发送数据
     */
    xhr.open()
    xhr.send(data)
    
    • 设置请求头
    xhr.setRequestHeader(key, value)
    // 一般前后端使用 JSON 数据格式进行交互,所以我们要设置请求头为
    ('Content-Type', 'application/json')
    
  • 根据 xhr 的 readyState 属性判断状态
    readyState 属性的值

    • 0:请求未初始化,open 还没有调用
    • 1:服务器连接已建立,已经调用了 send(),正在发送请求
    • 2:服务器已经接收到请求
    • 3:服务器正在处理请求
    • 4:请求已经完成,浏览器已经接收到响应数据

    通过 XMLRequest 的 readyStateChange 事件感知 readyState 的变化

    xmlHttp.onreadyStateChange = function () {
      if (xmlHttp.readyState === 4 || xmlHttp.status === 200) {
        // 请求到正确的相应内容之后的操作
      }
    }
    

封装一个 AJAX,用于处理 POST 和 GET 请求

参数列表

参数 说明 类型 可选值 默认值
method 请求方法 String GET/POST GET
url 请求地址 String
async 是否异步 Boolean true/false true
data 请求参数 Object {}
cb 回调函数 Function func
const request = function (options) {
  let xhr = null
  // 对传递的数据格式化
  let params = fomateParams(options.data)
  // 兼容处理 IE6、IE7
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest()
  } else {
    xhr = new ActiveXObject()
  }
  
  /**
   * 判断请求类型
   * GET 请求直接把格式化后的数据拼接到 URL 后面,不需要设置请求头,不需要调用 send 方法
   * POST 请求,设置请求头,调用 send 方法,传入 处理后的数据
   */
  if (options.type === 'GET') {
    xhr.open(options.type, options.url + params, options.async)
  } else if (options.type === 'POST') {
    xhr.setRequestHeader('Content-type', 'application/x-www-from-urlencoded')
    xhr.open(options.type, options.url, options.async)
    xhr.send(params)
  }

  /**
   * 绑定 readystatechange 事件,判断响应信息
   */
  xhr.addEventListener('readystatechange', function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
      options.success(xhr.responseText)
    }
  })
  
  // 定义格式化数据的方法,把对象形式参数转换成 URL 形式的字符串
  const fomateParams = function (obj) {
    if (obj === null) {
      return null
    }
    let arr = []
    for (let key in obj) {
      arr.push(key + '=' + obj[key])
    }
    return arr.join('&')
  }
}

// 调用方法
request({
 method: 'GET',
 url: '',
 async: true,
 data: {
  username: 'tim',
  password: '123123123'
 },
 success: function (res) {
   console.log(res)
 }
})

上面是第一次写的版本,存在诸多问题

  • onreadystatechange 的字母都是小写,而不是驼峰 onReadyStateChange,readyStete 属性是驼峰
  • readystatechange 应该绑定在 open 方法调用之前,不然感知不到(前面明明说了 readyState 的五种状态,粗心阿)
  • 如果使用函数表达式定义格式化数据方法,那么就要放在使用它之前声明(函数表达式不会变量提升,函数声明才会)

改良过后

const request = function (options) {
  let xhr = null
  // 对传递的数据格式化
  let params = fomateParams(options.data)
  // 兼容处理 IE6、IE7
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest()
  } else {
    xhr = new ActiveXObject()
  }

  // readystatechange 事件绑定在 open 方法调用之前
  xhr.addEventListener('readystatechange', function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
      options.success(xhr.responseText)
    }
  })
  
  /**
   * 判断请求类型
   * GET 请求直接把格式化后的数据拼接到 URL 后面,不需要设置请求头,不需要调用 send 方法
   * POST 请求,设置请求头,调用 send 方法,传入 处理后的数据
   */
  if (options.type === 'GET') {
    xhr.open(options.type, options.url + params, options.async)
  } else if (options.type === 'POST') {
    xhr.setRequestHeader('Content-type', 'application/x-www-from-urlencoded')
    xhr.open(options.type, options.url, options.async)
    xhr.send(params)
  }
  
  // 函数表达式改为函数声明
  function fomateParams (obj) {
    if (obj === null) {
      return null
    }
    let arr = []
    for (let key in obj) {
      arr.push(key + '=' + obj[key])
    }
    return arr.join('&')
  }
}

2021.04.18 改

/**
     * @param url
     * @param method
     * @param data
     * @param successCallback
     * @param failCallback
     */
    function request(options) {
      let {url, method, async, data, successCallback, failCallback} = options
      // 定义xml对象,根据不同的浏览器使用不同的函数创建
      let xhr
      if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest()
      } else {
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
      }
      // 监听请求完成事件
      xhr.onreadystatechange = function (res) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          successCallback(xhr)
        } else {
          failCallback(xhr)
        }
      }
      
      if (method === 'GET') {
        if (data) {
          url = url + '?' + formateParam(data)
        }
        xhr.open(method, url, async)
        xhr.send(null)
      } else {
        xhr.open(method, url, async)
        xhr.send(data)
      }
      
    }
    
    function formateParam(data) {
      if (typeof data !== 'object' || data === null) {
        throw new TypeError('data is not object type')
      }
      if (JSON.stringify(data) === '{}') {
        return ''
      }
      let tempArr = []
      for (let key in data) {
        tempArr.push(key + '=' + data[key])
      }
      return tempArr.join('&')
    }
    
    let options = {
      url: 'https://www.baidu.com',
      method: 'GET',
      async: true,
      data: null,
      successCallback: function (res) {
        console.log(res)
      },
      failCallback: function (res) {
        console.log(res)
      }
    }

拓展空间

POST 与 GET 请求的区别

  • GET 一般用户请求数据,POST 一般用于向服务器发送数据,但不是绝对的,POST 也可用来请求数据。
  • GET 发送数据拼接在 url 后面,这就意味着我们不能通过 GET 传递过大的数据量;POST 传递参数通过 send 方法发送,服务端从请求体中获取数据。
  • GET 发送数据的长度有限制(虽然本身没有限制,但URL有长度限制,这是各浏览器厂商的限制),POST 无限制。
  • GET 请求比 POST 请求更加不安全,因为发送数据的时候直接暴露在 URL 中。
  • GET 请求会被浏览器主动缓存,POST 不会主动缓存,除非手动设置。
  • GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

TCP

三次握手

  • 客户端发送SYN,表明要向服务器建立连接。同时带上序列号ISN
  • 服务器返回ACK(序号为客户端序列号+1)作为确认。同时发送SYN作为应答(SYN的序列号为服务端唯一的序号)
  • 客户端发送ACK确认收到回复(序列号为服务端序列号+1)

为什么要三次握手

  • 第一次握手:证明了发送方能发数据
  • 第二次握手:ack确保了接收方能收数据,syn确保了接收方能发数据
  • 第三次握手:确保了发送方能收数据

常见 HTTP 响应码

  • 100 这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完成,则忽略它。
  • 200 OK 请求成功
  • 301 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。
  • 302 临时重定向
  • 304 Not Modified 如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。
  • 400 Bad Request 语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求;请求参数有误。
  • 401 Unauthorized 未授权
  • 403 Forbidden 禁止访问
  • 404 Not Found 未找到
  • 405 Method Not Allowed 请求方法错误
  • 500 Internal Server Error 服务器遇到了不知道如何处理的情况
  • 502 Bad Gateway 此错误响应表明服务器作为网关需要得到一个处理这个请求的响应,但是得到一个错误的响应
  • 504 Gateway Timeout 当服务器作为网关,不能及时得到响应时返回此错误代码。

你可能感兴趣的:(Ajax基础)