ajax改promise,AJAX和Promise

给request设置第四部分,但是在chrome上看不到,因为当method为get时, chrome 不让设置第四部分 ,只有修改method为post时可以展示在chorme上

对HTTP设置请求和处理响应

使用Node.js设置请求

request举例

GET / HTTP/1.1 //第一部分 method,path,http协议

Host: www.baidu.com //第二部分 都是 key:value 的形式

User-Agent: curl/7.54.0 //第二部分

Accept: */* //第二部分

Frank: xxx //第二部分

Content-Length: 10 //第二部分

Content-Type: application/x-www-form-urlencoded //第二部分

//第三部分为回车

1234567890 // 第四部分为请求的内容

使用 js 设置请求:

let request = new XMLHttpRequest()

request.open('post','/xxx') //设置第一部分

request.setRequestHeader('Tom','18') //设置第二部分

request.setRequestHeader('Content-type','x-www-urlencoded') //设置第二部分

//第三部分为回车,不需要设置

request.send('我是request的第四部分')

// 注意,如果method为get的时候,chrome无法看到对应的值,只有method为post时才可以在控制台显示

使用 js 获取响应

response 举例

HTTP/1.1 200 OK

Accept-Ranges: bytes

Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform

Connection: Keep-Alive

Content-Length: 2443

Content-Type: text/html

Date: Tue, 10 Oct 2017 09:14:05 GMT

Etag: "5886041d-98b"

Last-Modified: Mon, 23 Jan 2017 13:24:45 GMT

Pragma: no-cache

Server: bfe/1.0.8.18

Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/

使用 js 获取 响应

let s1 = requet.status //获取状态码 200

let s2 = request.statusText // 获取OK

let s3 = request.getResponseHeader('Content-Type') //获取Content-Type

let s4 = request.getAllResponseHeaders()

let request.responseText()

//获取第四部分

使用jQuery封装一个AJAX

封装1.0 版本-简单粗暴版本

封装2.0版本-参数为对象

上面封装出现的问题

封装3.0版本-添加Promise规范

封装1.0 版本-简单粗暴版本

上面我们使用 js 设置请求响应,我们使用了以下5行代码,自然我们会想,有没有什么办法能够使用尽可能少的代码就完成上述的工作呢?

let request = new XMLHttpRequest()

request.open('post','/xxx')

request.setRequestHeader('Tom','18')

request.setRequestHeader('Content-type','x-www-urlencoded')

request.send('我是request的第四部分')

我们设想,把上面的实现写成一个函数封装不就行了吗?

设想 : xxx.ajax = function(url,method,body,successFn,failFn){}

具体实现

//html

点我

//js

window.jQuery.ajax = function(url,method,body,successFn,failFn){

let request = new XMLHttpRequest()

requet.open(method,url)

request.onreadystatechange = ()=>{

if(request.readystate === 4){

if(request.status >= 200 && request.status <300){

successFn.call(undefined,request.responseText)

}else if(request.status >=400){

failFn.call(undefined,request)

}

}

}

request.send(body)

}

window.$ = window.jQuery

myButton.addEventListener('click',(e)=>{

window.jQuery.ajax(

'/xxx',

'get',

null,

(responseText)=>{console.log(1)},

(request)=>{console.log(2)}

)

})

不足:

写好第一次封装以后,感觉自我良好,美美的睡一觉,第二天早上起来,准备再次使用我们封装的函数时,发现有一些问题

window.jQuery.ajax(

'/xxx',

'get',

null,

(responseText)=>{console.log(1)},

(request)=>{console.log(2)}

)

/xxx 这表示啥意思?字符串?路径?

get 表示method=get,我知道

null 表示一脸懵逼

(responseText)=>{} 这个箭头函数表示什么?处理成功?处理失败?

(request)=>{console.log(2)} 这又是啥意思?表示处理成功还是失败你倒是说话啊?

可能你会说,这都不懂?傻x,第一个/xxx 不是一看就知道表示路径吗?具体参数你不会回去看你自己封装函数的时候设置的参数吗?

但是,

如果某一次的请求路径为 get 那怎么办?很容易误导大家以为这个method啊

还有,如果封装函数的目的就是为了便利快捷,每次使用还得回去看参数,不是很麻烦吗?

以及,当method为get的时候,第三部分为空,一般人看不懂啊!!

当method=get的时候,第三个参数能不能不写?

不!行!它会把后面的箭头函数作为参数传进去,因此使用 null 作为占位符

显然,我们的封装还有不足。

需求:

此时,我们迫切需要一个有结构的方法分别表示上面的参数

由此,我们想到了 object

封装2.0版本-参数为对象

使用 Object 作为参数,

优点:

直观性:key:value

传参:function(object){}

赋值: Object.xxx = yyy

arguments 当传入的对象参数为多个的时候进行判断 。

代码示例:

window.jQuery.ajax = function(options){

let url

if(arguments.length ===1){

url = options.url;

}else if(arguments.length ===2){

url = arguments[0]

options = arguments[1]

}

let method = options.method

let body = options.body

let successFn = options.successFn

let failFn = options.failFn

let headers = options.headers

let request = new XMLHttpRequest()

requet.open(method,url)

request.onreadystatechange = ()=>{

if(request.readystate === 4){

if(request.status >= 200 && request.status <300){

successFn.call(undefined,request.responseText)

}else if(request.status >=400){

failFn.call(undefined,request)

}

}

}

request.send(body)

}

window.$ = window.jQuery

//调用

myButton.addEventListener('click',(e)=>{

let obj = {

url:'/xxx',

method:'get',

headers:{

'content-type':'application/x-www-urlencoded',

'frank':18

},

successFn:(e)=>{ //如果参数里面有多个函数,直接在箭头函数里面写多个函数即可

f1.call()

f2.call()

} //回调函数,e是 request.responseText

failFn:(e)=>{console.log(e)} //回调函数,e是request

}

window.jQuery.ajax(obj)

})

现在我们再看调用的代码

myButton.addEventListener('click',(e)=>{

let obj = {

url:'/xxx',

method:'get',

successFn:(e)=>{console.log('success')}

failFn:(e)=>{console.log(e)}

}

window.jQuery.ajax(obj)

})

问题:

如果成功了是否可一执行2个函数?

实现:在箭头函数里面放2个函数

successFn:(e)=>{ //如果参数里面有多个函数,直接在箭头函数里面写多个函数即可

f1.call()

f2.call()

}

当请求失败的时候返回状态码为 404,是否会返回内容?

答案;会的,依然可以设置第四部分的的返回值。

如何设置header ?

实现:

myButton.addEventListener('click',(e)=>{

let obj = {

url:'/xxx',

method:'get',

headers:{

'content-type':'application/x-www-urlencoded',

'frank':18

},

successFn:(e)=>{console.log('success')}

failFn:(e)=>{console.log(e)}

}

window.jQuery.ajax(obj)

})

获取 header

//省略部分代码...

let headers = options.headers

for(let key in headers){

let value = headers[key]

request.setRequestHeader(key,value)

}

当传入的参数为多个的时候,例如 function(url,object)怎么处理 ?

先判断 arguments 的长度。

再分别进行处理

window.jQuery.ajax = function(options){

let url

if(arguments.length ===1){

url = options.url;

}else if(arguments.length ===2){

url = arguments[0]

options = arguments[1]

}

升级:使用ES6语法的解构赋值进行优化

看代码:

let method = options.method

let body = options.body

let successFn = options.successFn

let failFn = options.failFn

let headers = options.headers

都是 使用 let 声明 ,显得累赘

let {method,body.successFn,failFn,headers} = options //等同于上面的5行

再次优化 :直接放入函数参数中

window.jQuery.ajax = function({method,body.successFn,failFn,headers}){

//省略部分代码

}

小结

上面几个步骤,看看我们从最简单粗暴的写法到逐步封装我们做了什么

第一步:瘦身,即对原来的代码进行封装,由多行到一个函数,通过传入参数进行赋值;

第二步:引入Object的结构化,即避免了每次调用函数的时候都去看我们封装的时候的参数是什么,同时赋值很方便;

第三步:使用ES6 解构赋值的语法对我们的封装函数进行改造,减少重复代码。

问题:如果多个不同的开发人员都对同一个AJAX进行了封装,会出现什么问题呢?

如下代码:

//jack

jack.ajax = function(null,null,succcess,fail){}

//tom

tom.ajax(function(error,content){

if(error){

// fail

}else{

//success

}

})

//smith

smith.ajax.onload = function(){}

smith.ajax.onerror = function(){}

即:

每个人对请求成功和失败的命名和处理方式不同,此时,我们需要一个统一化标准,怎么办?

Promise 的使用

目的和作用:

封装形式规范化

then 的使用和作用

function success(responseText){console.log(responseText)}

function fail(request){console.log(request)}

myButton.addEventListener('click',(e)={

$.ajax({

url:'/xxx'

method:'get'

}).then(success,fail)

})

我们看到,在jQuery里面把 success 和 fail 的处理方式放在 then 里面,第一个参数表示成功,第二个参数表示失败。

then() 返回的依然是Promise,在后面可以再不断地 then()

myButton.addEventListener('click',(e)={

$.ajax({

url:'/xxx'

method:'get'

}).then(success,fail).then(

success执行以后处理这里的函数,

fail执行以后处理这里的函数

)

})

小问题:

myButton.addEventListener('click',(e)={

$.ajax({

url:'/xxx'

method:'get'

}).then(

(responseText)=>{console.log(responseText)},

(request)=>{console.log(request)}

)

})

函数执行成功以后,即执行了 (responseText)=>{console.log(responseText)} 这行代码,返回的 responseText 为什么为对象而不是字符串?

答:因为jQuery 处理了,当jQuery 发现你的 response 的Content-Type:text/json; 时,它就会自动的把 responseText 转换成对象。

相当于 JSON.parse(responseText) ,返回为一个对象。 JSON.parse()—MDN

原理

window.Promise = function(){

//

return {

then(){}

}

}

具体使用:只需要记住这句代码

return new Promise(function(resolve,reject){})

参考文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值