AJAX是什么鬼 續(xù)篇
今天我們給AJAX封裝一下
之前寫了篇有關(guān)用原生JS寫jQuery的博客
下面是相關(guān)主要代碼
window.jQuery = function (nodeOrSelector) {
let nodes = {}
nodes.addClass = function () {}
nodes.html = function () {}
return nodes
}
事實上就是用函數(shù)給代碼封裝一下并設(shè)定相關(guān)參數(shù)
window.jQuery.ajax = function (url, method, body, succseeFn, failFn) {
let request = new XMLHttpRequest()
//初始化請求
request.open(method, url)
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
succseeFn.call(undefined, request.responseText)
} else if (request.status >= 400) {
failFn.call(undefined, request)
}
}
}
request.send(body)
}
window.$ = window.jQuery
可以使用$.ajax了
myButton.addEventListener('click', (e) => {
$.ajax(
'/ada',
'post',
'a=1&b=2',
(responseText) => {
console.log('s')
},
(request) => {
console.log('f')
})
})
但是這個$.ajax依然有問題
1.給定的參數(shù)順序太死
如果我不傳其中一個參數(shù),就需要給這個參數(shù)所在位置占位傅联,如若method是'get'先改,就不返回body,那就需要用undefined等占位
'/ada',
'post',
//null蒸走,undefined或'' 占位
'',
(responseText) => {
console.log('s')
},
(request) => {
console.log('f')
})
2.無法直觀解釋參數(shù)意思仇奶。
比如上面代碼,如果你沒看過前面內(nèi)容或者原生JS代碼比驻,你都不知道這些參數(shù)分別表達(dá)的是什么意思该溯。
解決方法:給參數(shù)命名唄
window.jQuery.ajax = function (options) {
//給參數(shù)一個選項
let method = options.method
let url = options.url
let body = options.body
let succseeFn = options.succseeFn
let failFn = options.failFn
let request = new XMLHttpRequest()
//初始化請求
request.open(method, url)
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
succseeFn.call(undefined, request.responseText)
} else if (request.status >= 400) {
failFn.call(undefined, request)
}
}
}
request.send(body)
}
myButton.addEventListener('click', (e) => {
//以對象的形式傳參數(shù)
$.ajax({
url: '/ada',
method: 'post',
body: 'a=1&b=2',
succseeFn: (responseText) => {
console.log('s')
},
failFn: (request) => {
console.log('f')
}
})
})
加一個 setRequestHeader:設(shè)置請求第二部分
headers: {
'content-type':'application/x-www-form-urlencoded'
}
$.ajax 部分遍歷一下 headers
let headers = options.headers
//下面代碼放在 requset.open() 后
for (let key in headers) {
let value = headers[key]
request.setRequestHeader(key, value)
}
如何向 $.ajax 傳兩個參數(shù):如 jQuery.ajax( url [, options ] )
let url
if(arguments.length === 1){
url = options.url
}else if(arguments.length === 2){
url = arguments[0]
options = arguments[1]
}
現(xiàn)在我們的$.ajax 已經(jīng)和jQuery的一樣了
優(yōu)化一下代碼岛抄,先不管兩個參數(shù)那個
1.ES6的 解構(gòu)賦值
//這6行代碼太丑了
let url= options
let method = options.method
let body = options.body
let succseeFn = options.succseeFn
let failFn = options.failFn
let headers = options.headers
//用ES6解構(gòu)賦值,上面代碼等價于
let = {url,method,body,headers,successFn,failFn} = options
可以不要 options 了
window.jQuery.ajax = function ({url,method,body,headers,succseeFn,failFn}){}
2.Promise,相關(guān)知識可以參考
之前我們給參數(shù)命名了狈茉,我是知道了這個參數(shù)代表什么夫椭。
但是每個人的命名都會不一樣,比如 jQuery 的 ajax 對響應(yīng)成功的命名就是 success 而我的是 successFn氯庆。
這對于不熟悉對應(yīng)文檔的人來說蹭秋,使用十分不便。
針對這個問題点晴,就有了 Promise
Promise的形式
window.Promise = function(fn){
//...
return {
then:function(){}
}
}
用Promise函數(shù):resolve,reject 替換 successFn 和 failFn感凤,這個兩個參數(shù)是ES6規(guī)定的,這樣就不會有上述問題了
return new Promise(function(resolve,reject){})
window.jQuery.ajax = function ({url,method,body,headers}) {
//之前代碼返回值是 undefined粒督,我們return一個Promise
return new Promise(function(resolve,reject){
let request = new XMLHttpRequest()
//初始化請求
request.open(method, url)
for (let key in headers) {
let value = headers[key]
request.setRequestHeader(key, value)
}
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
// successFn 就由 resove 代替了
resolve.call(undefined, request.responseText)
} else if (request.status >= 400) {
// failFn 就由 reject 代替了
reject.call(undefined, request)
}
}
}
request.send(body)
})
}
window.$ = window.jQuery
myButton.addEventListener('click', (e) => {
//以對象的形式傳參數(shù)
$.ajax({
url: '/ada',
method: 'post',
headers: {
'content-type': 'application/x-www-form-urlencoded',
'ada': '18'
}
}).then(
//成功后執(zhí)行的代碼
(responseText)=>{console.log(responseText)},
//失敗后執(zhí)行的代碼
(request)=>{console.log(request)}
)
})
then 后再 then
.then(
//成功后執(zhí)行的代碼
(responseText)=>{console.log(responseText);return '處理成功'},
//失敗后執(zhí)行的代碼
(request)=>{console.log(request);return '處理失敗'}
).then(
//上一次成功后的return
(responseText)=>{console.log(responseText)},
//上一次失敗后的return
(request)=>{console.log(request)}
)
可以看下結(jié)果完整代碼請看 github
小記
AJAX 的所有功能
客戶端的JS發(fā)起請求(瀏覽器上的)
服務(wù)端的JS發(fā)送響應(yīng)(Node.js上的)
1.JS 可以設(shè)置任意請求 header
第一部分 request.open(method, url)
第二部分 request.setRequstHeader('content-type','application/x-www-form-urlencoded')
第四部分 request.send(body)
2.JS 可以獲取任意響應(yīng) header
第一部分 request.status / request.statusText
第二部分 request.getResponseHeader() / request.getAllResponseHeaders()
第四部分 request.responseText
圖解
有關(guān)回調(diào) (callback:打電話回來):
succseeFn.call(undefined, request.responseText)
//這種形式就是回調(diào)
succseeFn: () => {}
promise 的 .then() 和 .then().then() 理解
.then(
fn1,fn2
).then(
fn3,fn4
)
.then( , ) 逗號左邊為成功執(zhí)行陪竿,右邊為失敗執(zhí)行
我們可以稱第一個: .then( fn1 , fn2 )為第一負(fù)責(zé)人;第二個: .then( fn3 , fn4 )為第二負(fù)責(zé)人
第一負(fù)責(zé)人成功則執(zhí)行 fn1 屠橄,失敗則執(zhí)行 fn2族跛;第一負(fù)責(zé)人處理完成處理則第二負(fù)責(zé)人執(zhí)行 fn3 ,處理不好(如代碼有問題)則執(zhí)行 fn4
本文僅供個人學(xué)習(xí)使用