4 Ajax

avatar
作者
猴君
阅读量:2

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 构造函数

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

2. XMLHttpRequest 属性

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 方法

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 方法

axios.create([config]) // 创建 axios 实例 

2. axios 请求配置

{    // `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 响应结构

{   // `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 配置默认值

// 全局的 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 添加拦截器

// 添加请求拦截器 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 移除拦截器

const myInterceptor = axios.interceptors.request.use(function () {/*...*/}); axios.interceptors.request.eject(myInterceptor); 

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

const instance = axios.create(); instance.interceptors.request.use(function () {/*...*/}); 

手写封装 axios 函数


/**  * ! 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 })) } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!