4 Ajax

Ajax 概述


Asynchronous JavaScript + XML(异步JavaScript和XML),其本身不是一种新技术,而是一个在 2005年被Jesse James Garrett提出的新术语,用来描述一种使用现有技术集合的'新'方法,包括: HTML 或 XHTML, CSS,JavaScript,DOM,XML,XSLT,以及最重要的 XMLHttpRequest;当使用结合了这些技术的AJAX模型以后, 网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面;这使得程序能够更快地回应用户的操作;
尽管X在Ajax中代表XML,但由于JSON的许多优势,比如更加轻量以及作为Javascript的一部分,目前JSON的使用比XML更加普遍;JSON和XML都被用于在Ajax模型中打包信息;

Ajax 优点:

  1. 最大的一点是页面无刷新,用户的体验非常好
  2. 使用异步方式与服务器通信,具有更加迅速的响应能力
  3. 可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担, Ajax的原则是"按需取数据",可以最大程度的减少冗余请求,和响应对服务器造成的负担
  4. 基于标准化的并被广泛支持的技术,不需要下载插件或者小程序

Ajax 缺点:

  1. Ajax不支持浏览器back按钮
  2. 安全问题,Ajax暴露了与服务器交互的细节
  3. 对搜索引擎的支持比较弱
  4. 破坏了程序的异常机制

Ajax 工作流程


  1. 网页中发生一个事件(页面加载、按钮点击)
  2. 由 JavaScript 创建 XMLHttpRequest 对象
  3. XMLHttpRequest 对象向 web 服务器发送请求
  4. 服务器处理该请求
  5. 服务器将响应发送回网页
  6. 由 JavaScript 读取响应
  7. 由 JavaScript 执行正确的动作(比如更新页面)

Ajax适用场景

  1. 表单驱动的交互
  2. 深层次的树的导航
  3. 快速的用户与用户间的交流响应
  4. 类似投票、yes/no等无关痛痒的场景
  5. 对数据进行过滤和操纵相关数据的场景
  6. 普通的文本输入提示和自动完成的场景

Ajax不适用场景

  1. 部分简单的表单
  2. 搜索
  3. 基本的导航
  4. 替换大量的文本
  5. 对呈现的操纵

XMLHttpRequest API


XMLHttpRequest(XHR)对象用于与服务器交互;通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据;这允许网页在不影响用户操作的情况下,更新页面的局部内容;XMLHttpRequest 在 AJAX 编程中被大量使用;

尽管名称如此,XMLHttpRequest 可以用于获取任何类型的数据,而不仅仅是 XML;它甚至支持 HTTP 以外的协议(包括 file:// 和 FTP),尽管可能受到更多出于安全等原因的限制;

如果您的通信流程需要从服务器端接收事件或消息数据,请考虑通过 EventSource 接口使用 server-sent events;对于全双工的通信, WebSocket 可能是更好的选择;

1. XMLHttpRequest 构造函数

sass 复制代码
XMLHttpRequest() // 该构造函数用于初始化一个 XMLHttpRequest 实例对象;在调用下列任何其他方法之前,必须先调用该构造函数,或通过其他方式,得到一个实例对象;

2. XMLHttpRequest 属性

sass 复制代码
XMLHttpRequest.readyState // 只读,返回一个 XMLHttpRequest  代理当前所处的状态
    - 0	- UNSENT -- XMLHttpRequest 代理已被创建,但尚未调用 open() 方法
    - 1 - OPENED -- open() 方法已经被触发;在这个状态中,可以通过 setRequestHeader() 方法来设置请求的头部,可以调用 send() 方法来发起请求
    - 2 - HEADERS_RECEIVED -- send() 方法已经被调用,响应头也已经被接收
    - 3 - LOADING -- 响应体部分正在被接收;如果 responseType 属性是"text"或空字符串,responseText 将会在载入的过程中拥有部分响应数据
    - 4 - DONE -- 请求操作已经完成;这意味着数据传输已经彻底完成或失败

XMLHttpRequest.status // 只读,返回 XMLHttpRequest 响应中的数字状态码
    - 只读属性 XMLHttpRequest.status 返回了XMLHttpRequest 响应中的数字状态码
    - status 的值是一个无符号短整型;在请求完成前,status的值为0
    - 值得注意的是,如果 XMLHttpRequest 出错,浏览器返回的 status 也为0

XMLHttpRequest.responseText // 只读,一个请求被发送后,从服务器端返回文本

3. XMLHttpRequest 方法

sass 复制代码
XMLHttpRequest.open(method,url,async,user,password) // 初始化一个请求
    - method -- 要使用的HTTP方法
    - url -- 一个DOMString表示要向其发送请求的URL
    - async -- 一个可选的布尔参数,表示是否异步执行操作,默认为true;如果值为false,send()方法直到收到答复前不会返回;如果true,已完成事务的通知可供事件监听器使用;如果
multipart属性为true则这个必须为true,否则将引发异常
    - user -- 可选的用户名用于认证用途;默认为null
    - password -- 可选的密码用于认证用途;默认为null

XMLHttpRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded') // 设置HTTP请求头部的方法;此方法必须在 open() 方法和 send() 之间调用
    - 如果没有设置 Accept 头部信息,则会发送带有 "*/*" 的Accept 头部

XMLHttpRequest.send(body) // 用于发送 HTTP 请求;如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回
    - body -- 在XHR请求中要发送的数据体. 可以是 Document,在这种情况下,它在发送之前被序列化

XMLHttpRequest.onreadystatechange = callback // 监听 readyState 属性发生变化触发

axios (网络请求库)


1. axios 方法

javascript 复制代码
axios.create([config]) // 创建 axios 实例

2. axios 请求配置

javascript 复制代码
{
   // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get',// default

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL;
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT','POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data,headers) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `headers` 是即将被发送的自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },

   // `paramsSerializer` 是一个负责 `params` 序列化的函数
  // (e.g. https://www.npmjs.com/package/qs,http://api.jquery.com/jquery.param/)
  paramsSerializer: function(params) {
    return Qs.stringify(params,{arrayFormat: 'brackets'})
  },

  // `data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT','POST',和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string,plain object,ArrayBuffer,ArrayBufferView,URLSearchParams
  // - 浏览器专属:FormData,File,Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,

   // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false,// default

  // `adapter` 允许自定义处理请求,以使测试更轻松
  // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  adapter: function (config) {
    /* ... */
  },

 // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

   // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer','blob','document','json','text','stream'
  responseType: 'json',// default

  // `responseEncoding` indicates encoding to use for decoding responses
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8',// default

   // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
  xsrfCookieName: 'XSRF-TOKEN',// default

  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
  xsrfHeaderName: 'X-XSRF-TOKEN',// default

   // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress: function (progressEvent) {
    // Do whatever you want with the native progress event
  },

  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress: function (progressEvent) {
    // 对原生进度事件的处理
  },

   // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise ;如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },

  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5,// default

  // `socketPath` defines a UNIX Socket to be used in node.js.
  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
  // Only either `socketPath` or `proxy` can be specified.
  // If both are specified,`socketPath` is used.
  socketPath: null,// default

  // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理;允许像这样配置选项:
  // `keepAlive` 默认没有启用
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // 'proxy' 定义代理服务器的主机名称和端口
  // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头;
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken: new CancelToken(function (cancel) {
  })
}

3. axios 响应结构

javascript 复制代码
{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

   // `config` 是为请求提供的配置信息
  config: {},
 // 'request'
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance the browser
  request: {}
}

4. axios 配置默认值

javascript 复制代码
// 全局的 axios 默认值
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

// 在创建 axios 实例的同时,自定义实例默认值
const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});

5. axios 拦截器

在请求或响应被 thencatch 处理前拦截它们

5.1 添加拦截器

javascript 复制代码
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  },function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  },function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

5.2 移除拦截器

javascript 复制代码
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

5.3 为自定义 axios 实例添加拦截器

javascript 复制代码
const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});

手写封装 axios 函数


javascript 复制代码
/**
 * ! Ajax 方法封装实现
 * * axios.get(url,options) 调用 axios 实现
 * * axios.post(url,options) 调用 axios 实现
 * * axios.put(url,options) 调用 axios 实现
 * * axios.delete(url,options) 调用 axios 实现
 */

/**
 * ! Ajax 封装
 *
 * @param {*} { method<请求方式>,url<请求地址>,params<请求参数>,data<请求体> }
 * @return {*} promise 对象
 */
function axios({ method,url,params,data }) {
  // method 转换大写
  method = method.toUpperCase()

  // 返回 promise 对象
  return new Promise((resolve,reject) => {
    // 请求四步走

    // 1.创建对象
    const xhr = new XMLHttpRequest()

    // 2.初始化
    // 2.1 处理 params 对象 X=XXXX&X=XXX
    let str = ''
    for (const key in params) {
      str += `${key}=${params[key]}&`
    }
    str = str.slice(0,-1)
    xhr.open(method,url + '?' + str)

    // 3.发送
    if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
      // Content-type mime类型设置
      xhr.setRequestHeader('Content-type','application/json')
      // 设置请求体
      xhr.send(JSON.stringify(data))
    } else {
      xhr.send()
    }

    // 响应结果格式设置为 JSON 创建的 JS 对象
    xhr.responseType = 'json'
    // 4.处理结果
    // 现代写法(指定多个回调)
    xhr.addEventListener("load",()=>{})
    // 原有写法
    xhr.onreadystatechange = function () {
      // 判断 XMLHttpRequest 代理当前所处的状态 4 === 下载操作已完成;
      if (xhr.readyState === 4) {
        // 判断响应状态码
        if (xhr.status >= 200 && xhr.status < 300) {
          // 成功状态
          resolve({
            status: xhr.status,
            message: xhr.statusText,
            body: xhr.response,
          })
        } else {
          reject(new Error('请求失败,失败的状态码为:' + xhr.status))
        }
      }
    }
  })
}
axios.get = function (url,options='') {
  // 发起 Ajax 请求
  return axios(Object.assign(options,{ method: 'GET',url: url }))
}
axios.post = function (url,options='') {
  // 发起 Ajax 请求
  return axios(Object.assign(options,{ method: 'POST',url: url }))
}
axios.put = function (url,options='') {
  // 发起 Ajax 请求
  return axios(Object.assign(options,{ method: 'PUT',url: url }))
}
axios.delete = function (url,options='') {
  // 发起 Ajax 请求
  return axios(Object.assign(options,{ method: 'DELETE',url: url }))
}
相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax