浅谈异步请求(xhr 与 fetch)
这篇文章是5.10日张言学姐的分享会之后的感悟与小结,张言学姐原博为“浅析 XMLHttPRequest API与Fetch API”,原博地址:https://zhangyan123.github.io/2016/11/01/%E6%B5%85%E6%9E%90XHR%E4%B8%8EFetch/
异步
首先谈到异步,异步到底是个什么东西呢?
首先我们到一个表单提交页面看看。下图是一个普通的注册页面。
在很久之前,只有同步请求的时候,程序必须是按顺序执行的,这样很傻。。。。
为什么呢?假如我要提交上面那种表单,全部输入完了页面不会有任何反应,点击提交之后才会告诉你哪一项有问题,这个时候你要重新填表单。重新。。。。如果表单很长,你可能会砸电脑。
为了解决这种状况,js出现了异步。我们填表单,每填完一项。都会检查,错误就会报错。。。。像下面这样。
简直不要太良心。。。这就是同步和异步的区别。然后,稍微深入一下。
异步的机制是什么样呢。。。
难道就是多个函数一起执行么。。。
当然不是。。js是一门单线程的语言,这是什么意思。。。这就是说js在一个时间只能处理一个玩意儿。。。。
那这样有什么好处,为什么不一次处理多点呢。看下面这张图。
如果是单线程,那么任务a和任务b肯定是等另一个执行完了再去执行另一个(想象任务为一个函数)。but多线程的话,就可能任务a执行到一半,这个时候任务a在等待,处理器转而去处理任务b。
这样就避免不了可能会发生资源的抢占,也就是说,b不小心把a的东西破坏掉了。这样a再处理的时候就会发生错误。
这样也是有解决办法的。然而js选择了最简单粗暴的一种。。。就是。。。我就只做成单线程。。。。
现在再回到异步,那么js如何实现异步呢。如果一个函数的执行时间可能比较长(比如请求数据),js会先把这个函数拿到一边,处理下面的程序,等到处理器空闲了再处理这个函数。就像settimeout一样。
等待一段时间再执行。
就像上面的表单。你填表单的时候,处理器是空闲的。就顺便发送一下请求检查一下你的数据是不是符合要求。。。
XMLHttpRequest
嗯。。。这个玩意太长了不好念,所以一般咱们叫他XHR,嗨呀。这样念就舒服多了。。。
首先我们来解析一下这个单词,就是xml形式的http请求对吧。http请求就不多说了,但是xml是个啥。官方的话就是可拓展标记语言。其实呢,就是纯文本。。。而且要求很严格。。。他把要传输的东西变成纯文本方便你传输。。
这个玩意就是为了。。。嗯。。。和后端交互。。上代码吧。。。
var xhr = new XMLHttpRequest();
xhr.open('post', '/login');
xhr.responseType = 'json';
xhr.onload = function() { console.log(xhr.response); };
xhr.onerror = function() { console.log("Booo"); };
xhr.send(data);
这是很简易的写法。。。平时不能这样写。。。
首先咱们新建一个xhr对象。。。为了传输数据。。。那么底下的内容。。。就是他要干的事情。。
首先开始一个请求open()。。。
表示我要开始准备请求,第一个传入值是请求方式,第二个是url地址。第一个值是post代表上传,get的话就代表索取。。。。
然后第三行是咱们说明一个返回值的数据类型。这里是json类型。。。一般也都用这个。。因为方便。。也可以用xml但是因为太严格。。不太好用。。
声明一下json和jsonp完全不是一个类型的东西。。jsonp和ajax也没有关系!!
具体看这http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html
然后第四行和第五行就是上传成功或者出错了得到的东西,相当于一个事件监听器。。
准备工作基本做完了。剩下的就是把请求发送了。。send一下。data是要发送的数据。。
如果要处理兼容性啊,要处理请求啊,根据不同的状态做出反应啊。。你就要写出这样的代码。。。
var xmlhttp, data=new FormData(); data.append('mail','15527216125@163.com'); data.append('password','123456') if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); }else if(window.ActiveXObject) { var versions=[ 'MSXML2.XMLHTTP.3.0', ' MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ]; for(var i=0;i< versions.length;i++) { try{ xmlhttp=new ActiveXobject(versions[i]); break; } catch(e){} } } xmlhttp.onreadystatechange = function () { if ( xmlhttp.readyState == 4 && xmlhttp.status == 200 ) { console.log(JSON.parse(xmlhttp.responseText); } }; xmlhttp.open("post", '/login' , false); //初始化XHR对象, readystate=1 xmlhttp.send(data); //参数用于传输 data readystate=2 // xmlhttp.abort(); //停止请求,用于多次连续点击处理及时禁止回调
心态崩了对不对。。我也不解释它了。。。然后。。。jqery就来了个$.ajax。
把所有的东西封装了起来。。。
变成了这个样子。。。
jQuery: $.ajax({ url: '/login', method: 'post', data:{mail:'15527216125@163.com',password:'123456'}, success:function(res){console.log(res)} });
瞬间觉得离不开jqery了对不对!!!
而且,jqery还把jsonp装在了这个东西里面!!可以方便的跨域了!!这就很舒服。。。。
但是首先呐,这样咱们就离不开jqery了,仿若被绑架。。其次又有一个问题。。。。回调地狱。。。。
自此开始下一个小标题。。
promise与fetch
嘛,既然是异步的请求,那么如果有多个他们回来的顺序怎么确定呢。。。
答案是!!随机!!看处理快慢喽。。
突然感觉仿若智障一样。。。假如我要查询一个地方的天气。。。来看下面的伪代码。。。
func1(){ //发送请求,获得国家 } func2(){ //根据国家,发送请求,获得省份 } func3(){ //根据省份,发送请求,获得天气 }
你说你是随机的。。exo me?那如果我func1请求是最慢的。。。那剩下的两个函数就报error了嘛?
那只能说。。是的。。。
那么该怎么解决呢。。。这就发生了回调地狱。。。。
(func(){ //纯纯的伪代码 $.ajax({ //... success:function(){ //fun1 获得了国家 $.ajax({ //... success:function(){ //func2...获得了省份 ………………………………………. } } }); } }) })();
如果毁掉次数很多。。。。。。。。。。。那眼睛就吓掉了。。。。
这时候出现了promise。。。这个东西的then方法可以解决这个问题。。。。。。。。。。。。。
具体看promise到底是什么东西看这里http://www.cnblogs.com/lvdabao/p/es6-promise-1.html
刚刚好。fetch返回的又是一个promise对象。,好完美。。。。。那么咱们可以这样
fetch(...).then(fun2) .then(fun3)//各依赖有序执行
回调地狱看起来就舒服多了。。。
process的功能可不止这些。他是一个很强大的对象。。。解决了很多异步问题。。具体的在上面博客看。。。
所以呀,fetch也就很神奇。。而且我们也可以用原生的js了。。。ps(fetch用起来甚至像jqery一样简单。。。)
以上便是整理的浅谈内容。。。