AJAX 出现以后解决了先后端交互问题,前端也正式走向前台。
AJAX 最核心的8句话前端
1. let request = new XMLHttpRequest() 2. request.onreadystatechange = () => { 3. if(request.state === 4){ console.log(request.status) //获取状态码 console.log(request.statusText) //获取状态码后面的OK 4. if(request.status === 200){ console.log(request.getResponseHeader('Content-Type')) //获取响应中第二部分某个内容 console.log(request.getAllResponseHeaders) //获取响应中第二部分全部的内容 console.log(request.responseText) //获取响应中第四部分 5. let string = request.responseText 6. let object = window.JSON.parse(string) } } } 7. request.open('get','http://baidu.com:8000/xxx') //设置请求中第一部分和第二部分的HOST request.setRequestHeader('Content-Type','application-www-form-urlencoded') //设置请求中第二部分 8. request.send('我偏要设置'') //设置请求中第四部分
HTTP 请求四部分ajax
第一部分:GET /xxx HTTP/1.1 //经过request.open()设置 第二部分:HOST : http://budu.com:8000 //经过request.setRequestHeader()设置,放在request.open()和request.send()之间 Content-Type : application/x-www-url-encoded 第三部分:回车,不须要设置 第四部分:我偏要设置 //经过reuqest.send()设置,GET请浏览器默认不展现,POST状况能够
HTTP 响应四部分json
第一部分:HTTP/1.1 200 OK //经过 request.status / reques.statusText 获取 第二部分:Content-Type : text/json;charset=utf-8 //经过 request.getResponseHeader / request.getAllResponseHeaders 获取 第三部分:回车,不须要设置 第四部分:文本 //经过 request.responseText 获取
用一张图简单的画下先后端交互的过程segmentfault
浏览器是在下载完全部响应内容后才知道响应结果吗?后端
服务器在发送响应时,假设response
中内容很大很大,那要等到全部内容都下载完才知道响应结果吗?未免体验太差了吧,因此response
中第一部份内容就已经把响应结果传递给浏览器。而咱们作判断时,为何先判断state === 4
,再判断响应结果呢?若是内容都尚未下载完毕,你获取到了响应结果也没有用,又不能获取里面的内容,因此才等都下载完了以后在去判断浏览器
window.jQuery.ajax = function({url,method,body,successFn,failFn}){ let xhr = new XMLHttpRequest() xhr.onreadtstatechange = function(){ if(xhr.readystate === 4 ){ if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){ successFn.call(undefined,xhr.responseText) }else if(request.status >=400){ failFn.call(uncefined,xhr) } } } request.open(method,url) request.send(body) }
当再点击按钮时,直接调用封装好的 API服务器
myButton.addEventLinstener('click',funtion(){ window.jQuery.ajax({ url : '/xxx', method : 'post', headers : { 'Content-Type' : 'application / x-www- form-urlencoded, 'zhangsan' : '19' }, body : 'a&b', successFn : (responseText) => {}, failFn : (request) => {} }) })
点击按钮时,调用 jQuery.ajax 时传递的函数是回调函数,它定义本身没有用,而是让别人用,别人用调用时会传递一个参数,因此回调函数的参数是肯定的。app
如今成功以后是能够把函数打印出来的,那若是成功后要打印两个函数怎么办。以下异步
function f1(responseText){} function f2(responseText){} successFn : (responseText) => { f1.call(undefined,responseText) f2.call(undefined,responseText) }
用回调最大的问题是回调函数没有命名规范,每一个开发者都有本身的风格,一旦引用了多个库,各个库之间的 ajax 回调函数可能会互相影响,Promise 的出现正好解决了这个问题。函数
function success(responseText){ console.log(1) } function fail(request){ console.log(2) } myButton.addEventListener('click',(e) => { $.ajax({ url : '/xxx' method : 'post' }).then(success,fail) })
$.ajax
,调用ajax
函数,它会返回一个Promise
,若是成功了会调用success
函数,若是失败了会调用fail
函数。
虽然仍是要传递函数,可是能够不用写函数名
myButton.addEventListener('click',(e) => { $.ajax({ url : '/xxx' method : 'post' }).then( (responseText) => {console.log(responseText)}, (request) => {console.log('error')} ) })
第一个成功函数的return
的值会串到第二个成功函数上
myButton.addEventListener('click',(e) => { $.ajax({ url : '/xxx' method : 'post' }).then( (responseText) => { console.log(responseText); return responseText }, (request) => { console.log('error'); return '已经处理' } ).then( (responseText) => {console.log(responseText)}, //responseText 应该是上一次处理的结果,jQuery会把它变成Object (request) => {console.log('error')} })
由于jQuery发现返回值的Content-Type
是text/json
,它就会自动把它由 String 变成 Object。
window.jQuery.ajax = function(url,method,body,headers){ return new Promise(function(resolve,reject){ //若是成功了就调用resolve,失败了调用reject let xhr = new XMLHttpRequest() for(let key in headers){ let value = headers[key] xhr.setRequestHeader(key,value) } xhr.onreadtstatechange = function(){ if(xhr.readystate === 4 ){ if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){ resolve.call(undefined,xhr) }else if(request.status >=400){ reject.call(uncefined,xhr) } } } xhr.open(method,url) request.send(body) } })
AJAX 要必需要return new Promise
,而后把你要作的事情放在new Promise
里面成功就调用resolve
,失败就调用reject
,Promise
会提供一个then
的 API,then
接收两个函数,成功就会调用第一个函数,失败调用第二个函数。
什么是回调?
简单说,就是将函数 A 做为参数传入函数 B
function A(){} function B(fn){fn.call()} B(A) // A 就是回调函数
具体的内容能够看这篇文章:异步与回调