本文转载于 SegmentFault 社区社区专栏:前端百变机器猫作者:bilibili



对于前端来说,请求是前端日常工作必备的,通过请求才能与后端进行数据交互,尤其在现在前后端分离的开发模式下,请求显得就更加重要。因此,对于前端开发者来说,掌握请求就很重要。下面将从http 请求和常见的几个请求技术做具体的讲解。


No.1

XMLHttpRequest

XMLHttpRequest一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,按照标准前后可以分为两个版本,具体阐述如下:

版本一(老版本):
//新建一个XMLHttpRequest对象var xhr=new XMLHttpRequest();

//进行请求xhr.open('GET', 'url');xhr.send();

//等待服务器响应xhr.onreadystatechange = function(){//该函数会被调用四次,因此需要判断状态是否为4if ( xhr.readyState == 4 && xhr.status == 200 ) {      alert( xhr.responseText );

    } else {

      alert( xhr.statusText );

    }};

在老版本中的,对应的具体属性说明如下:1.xhr.readyState:XMLHttpRequest 对象的状态,等于 4 表示数据已经接收完毕。2. xhr.status:服务器返回的状态码,等于 200 表示一切正常。3. xhr.responseText:服务器返回的文本数据4. xhr.responseXML:服务器返回的 XML 格式的数据5. xhr.statusText:服务器返回的状态文本。老版本因为不是统一的标准,各个浏览器厂商在实现的时候都有一定的差异,而且在存在一些缺陷:1. 只支持文本数据的传送,无法用来读取和上传二进制文件。2. 传送和接收数据时,没有进度信息,只能提示有没有完成。3. 受到"同域限制"(Same Origin Policy),只能向同一域名的服务器请求数据。

版本二(标准后的版本):

为了更好的使用 XMLHttpRequest,w3school 发布了标准版本,该版本弥补了版本一的缺陷,也被各大浏览器厂商接受并实现。具体为:1. 可以设置 HTTP 请求的时限。2. 可以使用 FormData 对象管理表单数据。3. 可以上传文件。4. 可以请求不同域名下的数据(跨域请求)。5. 可以获取服务器端的二进制数据。6. 可以获得数据传输的进度信息。当然,一般为了友好的进行兼容各个浏览器,会采用对浏览器进行判断并进行兼容性模式来获取XMLHttpRequest的对象。

var xhr;if (window.XMLHttpRequest) { // Mozilla, Safari...  xhr = new XMLHttpRequest();} else if (window.ActiveXObject) { // IEtry {    xhr = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) {try {      xhr = new ActiveXObject('Microsoft.XMLHTTP'); //IE5,6 } catch (e) {} }}// 请求成功回调函数xhr.onload = e => {console.log('request success');};// 请求结束xhr.onloadend = e => {console.log('request loadend');};// 请求出错xhr.onerror = e => {console.log('request error');};// 请求超时xhr.ontimeout = e => {console.log('request timeout');};// 请求回调函数.XMLHttpRequest标准又分为Level 1和Level 2,这是Level 1和的回调处理方式// xhr.onreadystatechange = () => {//  if (xhr.readyState !== 4) {//  return;//  }//  const status = xhr.status;//  if ((status >= 200 && status < 300) || status === 304) {//  console.log('request success');//  } else {//  console.log('request error');//  }//  };

xhr.timeout = 0; // 设置超时时间,0表示永不超时// 初始化请求xhr.open('GET/POST/DELETE/...', '/url', true || false);// 设置期望的返回数据类型 'json' 'text' 'document' ...xhr.responseType = '';// 设置请求头xhr.setRequestHeader('', '');// 发送请求xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');

No.2

ajax 请求

AJAX是一种与服务器交换数据的技术,可以在不重新载入整个页面的情况下更新网页的一部分,其实就是对XMLHttpRequest的封装,可以直接引入 jquery工具包来进行调用 ajax请求(jquery 是一个 js 工具包,其特点是:写得少,做得多),具体的ajax常用方式如下:

优点:
  • 对原生 XHR 的封装
  • 针对 MVC 的编程
  • 完美的兼容性
  • 支持 jsonp
缺点:
  • 不符合 MVVM
  • 异步模型不够现代,不支持链式,代码可读性差
  • 整个 Jquery 太大,引入成本过高

当然,我们可以直接使用 XMLHttpReqeust来进行实现自己的 ajax封装,具体代码如下:

const http = {/**   * js封装ajax请求   * >>使用new XMLHttpRequest 创建请求对象,所以不考虑低端IE浏览器(IE6及以下不支持XMLHttpRequest)   * >>使用es6语法,如果需要在正式环境使用,则可以用babel转换为es5语法 https://babeljs.cn/docs/setup/#installation   *  @param settings 请求参数模仿jQuery ajax   *  调用该方法,data参数需要和请求头Content-Type对应   *  Content-Type                        data                                     描述   *  application/x-www-form-urlencoded   'name=哈哈&age=12'或{name:'哈哈',age:12}  查询字符串,用&分割   *  application/json                     name=哈哈&age=12'                        json字符串   *  multipart/form-data                  new FormData()                           FormData对象,当为FormData类型,不要手动设置Content-Type   *  注意:请求参数如果包含日期类型.是否能请求成功需要后台接口配合   */  ajax: (settings = {}) => {// 初始化请求参数let _s = Object.assign({      url: '', // stringtype: 'GET', // string 'GET' 'POST' 'DELETE'      dataType: 'json', // string 期望的返回数据类型:'json' 'text' 'document' ...async: true, //  boolean true:异步请求 false:同步请求 required      data: null, // any 请求参数,data需要和请求头Content-Type对应      headers: {}, // object 请求头      timeout: 1000, // string 超时时间:0表示不设置超时      beforeSend: (xhr) => {      },      success: (result, status, xhr) => {      },      error: (xhr, status, error) => {      },      complete: (xhr, status) => {      }    }, settings);// 参数验证if (!_s.url || !_s.type || !_s.dataType || !_s.async) {      alert('参数有误');return;    }// 创建XMLHttpRequest请求对象let xhr = new XMLHttpRequest();// 请求开始回调函数    xhr.addEventListener('loadstart', e => {      _s.beforeSend(xhr);    });// 请求成功回调函数    xhr.addEventListener('load', e => {const status = xhr.status;if ((status >= 200 && status < 300) || status === 304) {let result;if (xhr.responseType === 'text') {          result = xhr.responseText;        } else if (xhr.responseType === 'document') {          result = xhr.responseXML;        } else {          result = xhr.response;        }// 注意:状态码200表示请求发送/接受成功,不表示业务处理成功        _s.success(result, status, xhr);      } else {        _s.error(xhr, status, e);      }    });// 请求结束    xhr.addEventListener('loadend', e => {      _s.complete(xhr, xhr.status);    });// 请求出错    xhr.addEventListener('error', e => {      _s.error(xhr, xhr.status, e);    });// 请求超时    xhr.addEventListener('timeout', e => {      _s.error(xhr, 408, e);    });let useUrlParam = false;let sType = _s.type.toUpperCase();// 如果是"简单"请求,则把data参数组装在url上if (sType === 'GET' || sType === 'DELETE') {      useUrlParam = true;      _s.url += http.getUrlParam(_s.url, _s.data);    }// 初始化请求    xhr.open(_s.type, _s.url, _s.async);// 设置期望的返回数据类型    xhr.responseType = _s.dataType;// 设置请求头for (const key of Object.keys(_s.headers)) {      xhr.setRequestHeader(key, _s.headers[key]);    }// 设置超时时间if (_s.async && _s.timeout) {      xhr.timeout = _s.timeout;    }// 发送请求.如果是简单请求,请求参数应为null.否则,请求参数类型需要和请求头Content-Type对应    xhr.send(useUrlParam ? null : http.getQueryData(_s.data));  },// 把参数data转为url查询参数  getUrlParam: (url, data) => {if (!data) {return '';    }let paramsStr = data instanceof Object ? http.getQueryString(data) : data;return (url.indexOf('?') !== -1) ? paramsStr : '?' + paramsStr;  },// 获取ajax请求参数  getQueryData: (data) => {if (!data) {return null;    }if (typeof data === 'string') {return data;    }if (data instanceof FormData) {return data;    }return http.getQueryString(data);  },// 把对象转为查询字符串  getQueryString: (data) => {let paramsArr = [];if (data instanceof Object) {Object.keys(data).forEach(key => {let val = data[key];// todo 参数Date类型需要根据后台api酌情处理if (val instanceof Date) {// val = dateFormat(val, 'yyyy-MM-dd hh:mm:ss');        }        paramsArr.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));      });    }return paramsArr.join('&');  }}

No.3

vue-resource 请求

vue-resource是 Vue.js的一款插件,它可以通过 XMLHttpRequest或 JSONP发起请求并处理响应。也就是说,$.ajax能做的事情,vue-resource插件一样也能做到,而且 vue-resource的 API更为简洁。另外,vue-resource还提供了非常有用的inteceptor 功能,使用inteceptor可以在请求前和请求后附加一些行为,比如使用 inteceptor在 ajax请求时显示 loading 界面。

特点:1. 体积小

vue-resource 非常小巧,在压缩以后只有大约 12KB,服务端启用 gzip 压缩后只有 4.5KB 大小,这远比 jQuery 的体积要小得多。2. 支持主流的浏览器  
和 Vue.js 一样,vue-resource 除了不支持 IE 9 以下的浏览器,其他主流的浏览器都支持。3. 支持 Promise API 和 URI Templates  
Promise 是 ES6 的特性,Promise 的中文含义为“先知”,Promise 对象用于异步计算。 
URI Templates 表示 URI 模板,有些类似于 ASP.NET MVC 的路由模板。4. 支持拦截器  
拦截器是全局的,拦截器可以在请求发送前和发送请求后做一些处理。 
拦截器在一些场景下会非常有用,比如请求发送前在 headers 中设置 access_token,或者在请求失败时,提供共通的处理方式。

常用api
  • get(url, [options])
  • head(url, [options])
  • delete(url, [options])
  • jsonp(url, [options])
  • post(url, [body], [options])
  • put(url, [body], [options])
  • patch(url, [body], [options])

option 详解


No.4

fetch

1. fetch 是基于 promise实现的,也可以结合 async/await2. fetch请求默认是不带 cookie的,需要设置 fetch(URL,{credentials:’include’})。 3. Credentials 有三种参数:same-origin,include,*4. 服务器返回 400 500 状态码时并不会 reject,只有网络出错导致请求不能完成时,fetch才会被 reject5. 所有版本的 IE 均不支持原生 Fetch6. fetch是 widow的一个方法

fetch(url).then(function(response) {return response.json();}).then(function(data) {  console.log(data);}).catch(function(e) {  console.log("Oops, error");});

可配合 es6 的箭头函数进行使用

fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))

No.5

axios

Axios是一个基于 promise的 HTTP库,可以用在浏览器和 node.js中

特点:
  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 PromiseAPI
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF
常用 api:
  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]]
实例:

get 请求

// 为给定 ID 的 user 创建请求axios.get('/user?ID=12345')  .then(function (response) {    console.log(response);  })  .catch(function (error) {    console.log(error);  });

// 可选地,上面的请求可以这样做axios.get('/user', {    params: {      ID: 12345    }  })  .then(function (response) {    console.log(response);  })  .catch(function (error) {    console.log(error);  });

post 请求

axios.post('/user', {    firstName: 'Fred',    lastName: 'Flintstone'  })  .then(function (response) {    console.log(response);  })  .catch(function (error) {    console.log(error);  });

并发请求 

function getUserAccount() {return axios.get('/user/12345');}

function getUserPermissions() {return axios.get('/user/12345/permissions');}

axios.all([getUserAccount(), getUserPermissions()])  .then(axios.spread(function (acct, perms) {    // 两个请求现在都执行完成  }));
拦截器
// 添加请求拦截器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);  });

取消请求

var CancelToken = axios.CancelToken;var source = CancelToken.source();

axios.get('/user/12345', {  cancelToken: source.token}).catch(function(thrown) {if (axios.isCancel(thrown)) {    console.log('Request canceled', thrown.message);  } else {// 处理错误  }});

// 取消请求(message 参数是可选的)source.cancel('Operation canceled by the user.');

当然,无论选择哪一种方式都需要自身结合业务的需要和自我的认知,没有哪个绝对的优秀,也没有哪个绝对不优秀。

- END -

ajax jq 图片上传请求头_前端常见面试 请求篇相关推荐

  1. ajax jq 图片上传请求头_全面分析前端的网络请求方式:Ajax ,jQuery ,axios,fetch

    链接:https://juejin.im/post/5c9ac607f265da6103588b31 一.前端进行网络请求的关注点 大多数情况下,在前端发起一个网络请求我们只需关注下面几点: 传入基本 ...

  2. ajax jq 图片上传请求头_Jquery ajaxsubmit上传图片实现代码

    这是数月前的事情了,场景是这样的: 在进行图片上传的时,我发现开发人员使用的上传图片方式是Iframe + 传统的 http post 来处理的. 而且未建立统一上传函数.于是将代码改造了.心想来个a ...

  3. ajax jq 图片上传请求头_如何使用js或jQuery向Ajax请求添加自定义HTTP头?

    下面是一个使用XHR 2的示例:function xhrToSend(){ // Attempt to creat the XHR2 object var xhr; try{ xhr = new XM ...

  4. ajax上传图片并显示,Ajax实现图片上传并预览

    效果见尾部. 最近在使用ThinkPHP5开发项目中客户有一个需求是在图片上传时附带预览功能.虽然现在有很多的插件能实现,但是还是觉得自己写比较好.我们知道,图片上传需要一个input:file表单 ...

  5. html ajax 图片上传,Ajax实现图片上传并预览功能

    先给大家展示下效果图,大家感觉不错,请参考实现代码. 最近在使用ThinkPHP5开发项目中客户有一个需求是在图片上传时附带预览功能.虽然现在有很多的插件能实现,但是还是觉得自己写比较好.我们知道,图 ...

  6. html显示数据库图片django,django将图片上传数据库后在前端显式的方法

    1.使用ImageField先安装pillow模块 pip install pillow 2.在app的models中设置 class Image(models.Model): pic_name=mo ...

  7. php模板多图上传插件,PHP+jQuery+Ajax多图片上传插件

    注:本地预览无效,需要在服务断运行 使用方法 HTML 首先我们在页面上放置个上传按钮,使用POST提交到ajax.php.#ul_pics 用来显示上传完毕后的图片.关于按钮.进度条.图片垂直居中样 ...

  8. Ajax实现图片上传并预览

    效果见尾部. 最近在使用ThinkPHP5开发项目中客户有一个需求是在图片上传时附带预览功能.虽然现在有很多的插件能实现,但是还是觉得自己写比较好.我们知道,图片上传需要一个input:file表单 ...

  9. c ajax 上传图片插件,ajax实现图片上传和预览

    图片上传功能 html结构: ![](6f4fbfb7/addimg.png) 在html中input的type=file就可以实现文件的上传功能,在其属性中也包含一个accept='':可以限制文件 ...

  10. php用ajaxs上传图片_jquery+ajax+php 图片上传

    最近在写"网上商城"的课程设计,用到了图片上传. 我要实现的功能主要有:(1)能够上传多张图片,不过当然是有限制的,最多5张:(2)能够进行图片预览:(3)能够删除图片:(4)服务 ...

最新文章

  1. cad菜单栏快捷键_拒绝效率低下,教你瞬间提升10倍!老师傅珍藏多年CAD快捷键...
  2. java getaccessflags_Java Method.getAccessFlags方法代码示例
  3. 亲测:阿里云的高效云盘真没有声称那么好
  4. linux 驱动没有设备id,linux不同总线的设备和驱动的匹配过程分析
  5. 表格打印没有左边线_office办公软件Excel表格的打印技巧,建议收藏
  6. 掌握计算机底层原理,可以让工作事半功倍吗?
  7. 将html内容转换成word文档,一招教你将网页内容转化为word文档保存
  8. FPGA20个例程专栏介绍
  9. android 外文翻译,Android外文文献翻译.doc
  10. 【项目实践】DCGAN绘制理想女朋友照片实践,从爬虫到生产女友
  11. 3.路由实现(phalapi框架总结)
  12. Mac运行ftp报错Error: JAVA_HOME is not defined correctly.
  13. springboot项目结构_从零搭建Spring Boot脚手架(1):开篇以及技术选型
  14. 3.知识图谱业务落地技术推荐之国内知识图谱平台汇总(竞品)[阿里、腾讯、华为等】
  15. 锚点是什么?锚点的使用
  16. 【图像超分辨率重建】——SAN论文精读笔记
  17. Tomcat - 解决which must be escaped when used within the value错误
  18. java娘_初识java这个小姑娘(二)
  19. CRM系统主要包含什么内容
  20. Ubuntu18.04.5-server网络配置介绍

热门文章

  1. 解析docx C语言,c语言习题解析【含基础知识讲解】.docx
  2. Android 学习思维导图
  3. Algs4-1.5.11实现加权quick-find算法
  4. LeetCode 144. Binary Tree Preorder Traversal 20170706
  5. LayoutInflater拦截View创建,自定义Resource对象
  6. Python学习笔记1—Python字符串
  7. 如何知道一个exe或者dll是用什么语言编译的
  8. 改变ALERT组件的背景色和背景透明度.
  9. js统计页面访问次数
  10. win10的文件夹(文件资源管理器)卡住了