带你了解AJAX-HTTP-PROMISE

228 阅读4分钟

####什么是AJAX

async javascript and xml :异步的JS 和 XML
此处的异步指的是:局部刷新(对应的是全局刷新)
XML:可扩展的标记语言,用自己定义的标签来存储数据的(在很早以前,我们基于AJAX和服务器进行交互的数据格式一般都以XML格式为主。因为它能清晰展示出对应的数据和层级结构;但是到后面,流行了一种新的数据格式JSON,它不仅比XML更清晰展示数据的结构,而且同样的数据存储,JSON更加轻量,也方便解析和相关的操作,所以现在前后端的数据交互都以JSON格式为主)
优缺点:XML用自己的方式存储数据也有层级但是操作麻烦;   XML格式偏大   ;;;;有时候XML可以和HTML一样直接呈现、渲染的

####AJAX的基础操作

1.创建AJAX实例
  let xhr=new XMLHttpRequest;//(通过Http的请求能够把XML得到) =》IE低版本浏览器中用的是new ActiveXObject()  IE6及IE6以下
2.打开URL(配置发送请求的信息)
  //method:HTTP请求方式
 //URL:请求地址(API接口地址)
 //async:设置同步或者异步,默认是true异步,false 同步
 //user-name:传递给服务器的用户名
 //user-pass:传递给服务器的密码
xhr.open('GET','./json/xxx.json',true)
3.监听AJAX状态,在状态为X的时候,获取服务器响应的内容
//AJAX状态码:0 1 2 3 4
xhr.onreadystatechange=function(){
if(xhr.readyState===4 && /^(2|3)\d{2}$/.test(xhr.status)){
let result=xhr.responseText;
}
}
4.发送请求
  //send中放的是请求主体的内容
  xhr.send(null);
=>AJAX任务(发送一个请求给服务器,从服务器获取到对应的内容)从send后开始,到xhr.readystate===4的时候算任务结束

=>{  readyState 状态值   status 状态     }
 2 -----响应头     
 4-------响应主体

####HTTP的请求方式

-》GET系列
     +Get
     +Delete :一般只用于告诉服务器,从服务器上删点东西;
     +Head:只想获取响应头内容,告诉服务器响应主体内容不要了;
     +Options:试探性请求,发个请求给服务器,看看服务器能不能接受到,能不能返回
-》POST系列
     +post
     +Put和delete对应,一般是想让服务器把我传递的信息存储到服务器上(一般应用于文件和大型数据内容,小的用post)

==》真实项目中用对应的请求方式,会使请求变得更加明确(语义化),不遵循这些方式也可以,最起码浏览器在语法上是允许的,但是这些是开发者们相互间约定俗成的规范;
    GET系列一般用于从服务器获取信息,POST系列一般用于给服务器推送信息,但是不论GET和POST都可以把信息传递给服务器,也能从服务器获取到结果,只不过是谁多谁少的问题
=》GET:给的少,拿的多   比如:渲染页面
=》POST:给的多,拿的是少  比如:注册
客户端怎么把信息传递给服务器?
--问号传参   xhr.open('GET','/getdata?xxx=xxx&xxx=xxx')
--设置请求头   xhr.setRequestHeader([key],[value]) //请求头里都是键值对 属性名:属性值
--设置请求主体   xhr.send(请求主体信息)
服务器怎么把信息返回给客户端?
--通过响应头
--通过响应体(大部分信息都是基于响应体返回的)
GET系列和POST系列的本质区别:
 》GET系列传递给服务器信息的方式一般采用:问号传参
 》POST系列传递给服务器信息的方式一般采用:设置请求主体//xhr.send('请求主题信息')

   1.GET传递给服务器的内容比POST少,因为URL有最长大小限制(IE浏览器一般限制2kB[2千多个字符],谷歌浏览器一般限制4~8kB,超过长度的部分自动被浏览器截取了)
eg:
xhr.open('GET','/lost?name=zhufeng&year=10&xxx=xxx...')
xhr.send('....') 请求主体中传递的内容理论上没有大小限制,但是真实项目中,为了保证传输的速度,我们会自己限制一些

   2.GET会产生缓存(缓存不是自己可控制的):因为请求的地址(尤其是问号传递的信息一样),浏览器有时候会认为你要和上次请求的数据一样,拿的是上一次信息;这种缓存我们不期望有,我们期望的缓存是自己可控制的,所以真实项目中,如果一个地址,get请求多次,我们要去除这个缓存;

//解决办法设置随机数
xhr.open('GET','/lost?name=zhufeng&_=+Math.random()');
   3.GET相比较POST来说不安全:GET是基于问号传参传递给服务器内容,有一种技术叫做URL劫持,这样别人可以获取或者篡改传递的信息,而POST基于请求主体传递信息,不容易被劫持;
    涉及安全用post
    大小 、 缓存、 安全

####AJAX的状态码

>xhr.readyState 获取状态码
--Unsend  0 :未发送(创建一个XHR,初始状态是0)
--Opened  1 :已经打开(执行了xhr.open)
--Headers_Received 2 :响应头信息已经返回给客户端(发送请求后,服务器会依次返回响应头和响应主体的信息   响应头先回来,因为东西少)
--Loading 3 :等待服务器返回响应内容
--Done 4 :响应主体信息已经返回给客户端

*xhr.getResponseHeader('DATA') 获取响应头信息
获取的服务器时间是标准的日期格式对象(GMT格林尼治时间),new Data() 能把格林尼治时间转换为北京时间
//new Data()获取的是当前客户端本机时间

=》获取响应主体信息:我们一般用responseText,因为服务器返回的信息一般都是JSON格式的字符串,如果返回的是XML格式,我们用responseXML...
1.responseXML  2.response   3.responseType   4.responseText

AJAX上面有七个方法

1.abort
2.getAllResponseHeaders 获取所有响应头信息
3.getResponseHeaders 获取响应头信息
4.overrideMimeType 重改overrideMimeType类型 5.send 6。open 7.setResponseHeader('AA','hahaha') AA:hahaha

=>AJAX的同步
  使用AJAX同步编程,不能在状态码为2的时候获取到响应头的信息,但是状态码为4的时候也是可以获取到头和主体信息
API:Application  Progrramming  Interface   凡是可被别人调用,并且给予反馈结果的都可以被称之为API接口
    JQuery 的 AJAX
$.ajax()基于原生js的AJAX四部操作进行封装
配置项信息
  1. url:请求的API接口地址
  2. method:HTTP请求方式,默认GET
  3. data:传递给服务器的信息,默认null(可以是字符串,可以是对象,而且如果GET系列请求,JQ会自动把信息拼接到URL的末尾,基于问号传参传递给服务器;如果是POST请求,JQ会基于请求主体,把信息传递给服务器)
    4.dataType:预设服务器返回的结果格式(服务器一般返回的都是JSON格式的字符串,如果我们设置了DATA-type,JQ会根据设置的类型,把服务器返回的结果处理为对应的格式),支持的内容text/json/xml/html/script/jsonp(跨域)=>dataType能不能影响服务器的返回结果?  不影响服务器返回的结果,只是把服务器返回的结果进行二次处理;
    5.async:是否为异步操作,默认是 TRUE,代表异步操作
    6.cache:缓存处理,只对get系列请求有作用,默认是true不处理缓存,当我们设置false后,JQ帮我们在url的末尾设置一个随机数
    7.contentType:设置传递给服务器内容的格式类型默认是"application/x-www-form-urlencoded"
         客户端传递给服务器信息的格式(类型一般都是字符串),常用的:
         form-data表单数据:JSON格式'{"name":"xxx","lx":1}'
         x-www-form-urlencoded:name=xxx&lx=1
         raw:纯文本格式
     8.headers:设置请求头信息,他是一个对象
     9.timeout:设置超时的时间
     10.success:回调函数,当数据请求成功执行,方法中的参数就是从服务器获取的结果
     11.error:回调函数,数据请求失败执行,方法中的参数是错误信息
$.ajax({
     url:'http://baidu.com',
     method:'GET',
     data:{
           name:'zhufeng',
           lx:'teacher'
          },
      dataType:'json',
      async:true,
      cache:false,
      headers:{},
      success:(result,status,xhr)=>{
       //=>xhr:是JQ帮我们处理过的AJAX实例
       console.log(result,status,xhr)
}
        
      
})

把一个函数加小括弧执行 能不能创造函数的实例 中转一下

####promise

>ES6语法规范中新增加的内置类,用来处理JS中异步编程的,而我们所谓的promise设计模式,就是基于promise对异步操作进行管理
=>AJAX串行:
  只有第一个请求成功才能执行第二个,第二个成功才能执行第三个....最后一个请求成功后拿到了每一次请求的所有数据
=>AJAX并行:
  三个请求可以同时发送,但是需要等到所有请求都成功才会做一件事
 => new Promise([executor]):第一个执行函数必须传递
   [executor 简称 EXE]
    1.New Promise的时候就会把EXE执行,创建promise的一个实例(EXE是promise类的一个回调函数,promise内部会把他执行){把一个函数作为值传给promise,new promise把这个函数执行了}
    2.promise不仅把EXE执行,而且还给EXE传递两个参数(两个参数也是函数类型):
    =》resolve函数:它执行代表promise处理的异步事情是成功的,把promise状态改为fulfilled
    =》reject函数:它执行代表promise处理的异步事情是失败的,把promise状态改为rejected
   3.EXE函数中放的就是当前要处理的异步操作事情
let ran=Math.random();
let promiseExamp=new promise((resolve,reject)=>{
//=>这里一般存放的都是我们即将处理的异步任务,任务成功我们执行resolve,任务失败我们执行reject(当让同步的也可以)
setTimeout(()=>{
if(ran<0.5){
reject(ran);
return;
  }
  resolve(ran)
 },1000);
});
//then就是成功之后做什么 失败之后做什么
promiseExamp.then(result=>{
//=》状态为fulfilled成功后执行(result:[[PromiseValue]])
console.log('成功:'+result);
},error=>{
 //=》状态为rejected失败后执行
 consloe.log('失败:'+error)
})

promiseExamp.catch(error=>{
 consloe.log('失败:'+error)
})

promiseExamp.finally(x=>{
 consloe.log('都会被执行')
})


Promise.prototype
  then:设置成功或者失败后执行的方法(成功或者失败都可以设置,也可以只设置一个)
     pro.then([success],[error])
     pro.then([success])
     pro.then(null,[error])
  catch:设置失败后执行的方法
  finally:设置不论成功还是失败都会执行的方法(一般不用)
PROMISE有三个状态
   pending:初始状态(NEW promise后的状态)
   fulfilled:成功状态(在executor函数中把resolve执行,就是告知promise当前异步操作的结果是成功的)
   rejected:失败状态(在executor函数中把reject执行,就是告知promise当前异步操作的结果是失败的)
then链
   执行then/catch/finally 返回的结果是一个全新的promise实例,所以可以链式写下去。下一个then中那个方式会被执行,由上一个then中某个方法执行的结果来决定;
   上一个then中某个方法的返回值会传递给下一个then的某个方法中
  如果当前promise实例的状态确定后,都会到对应的then中找方法,如果then中没有对应的这个方法,则会向下顺延
 

第一个promise实例,执行的是resolve状态是成功,promiseValue值是100,一定会执行A,then创建了第二个promise实例,会把A执行,A执行报错了会把第二个promise实例状态改为失败的,promiseValue值是报错原因,一定会走catch; 这个catch可以监听两个失败函数第一个和第二个promise实例 最后一个then走成功或者失败取决于catch里的函数是成功还是失败

·············································· 向下顺延

=>Then 方法中如果返回的是一个promise实例,则当前返回实例的成功或者失败状态,影响着下一个then中哪个方法会被触发执行;如果返回的是非promise实例,则看当前方法执行是否报错,来决定下一个then中哪个方法会被触发执行
Promise.ALL:可以解决并行
 function ajax1(){
    return new Promise(resolve=>{
        $.ajax({
            url:'/api1',
            success:resolve
            
        })
    })
}
//Promise.all([promise1,promise2,...]):All中存放的是多个promise实例(每一个实例管理者一个异步操作),执行All方法返回的结果是一个新的promise实例 “PROA”
//=》当所有promise实例的状态都为Fulfilled的时候(成功),让PROA的状态也变为Fulfilled,并且把所有promise成功获取的结果,存储为成为一个数组(顺序和最开始编写的顺序一致)“result[result1,result2,.....]”,让PROA这个数组的Value值等于这个数组
//=》都成功(PROA状态是Fufilled)才会通知then中第一个方法执行,只要有一个失败(PROA状态是Rejected),就会通知then中第二个方法或者catch中的方法执行;
function ajax1(){
    return new Promise(resolve=>{
        $.ajax({
            url:'/api1',
            success:resolve
        })
    })
}

Promise.all([ajax1(),ajax2(),ajax3()]).then(results=>{
//=>results:[result1,result2,result3]
})
Promise.race([ajax1(),ajax2(),ajax3()]).then(result=>{
//=>看那一个promise状态最先处理完(成功或者失败),以最先处理完的为主
});

记得点赞哦👍👍