手工实现 ajax,根据上一篇文章 原生js实现jsonp和ajax,我们只需将原生 js 优化为一个简洁的 api。本文的实现,从原生版 ajax 出发
看完本文,你将了解:
1.利用对象传参的套路将参数表简化
2.利用 ES6 的解构赋值去冗余
3.利用Promise和then,将参数表中的函数分离
4.以上技巧的应用
5.其他小知识
一. 对象传参套路
1.当一个函数具有多个参数的时候,调用也许不大直观,很难看出各个参数含义
如: process(null, 1, null, 2, null, null, null, 3)
这时可以考虑把参数打包成有结构的对象,传一个对象参数
使用对象传参的好处。一是逻辑明确,不必考虑哪个参数是在哪个位置,参数对应关系直接从键值对解析即可。二是扩展简单。
2.效果:
before:多个参数传入
after:一个对象传入
二. ES6语法:解构赋值与交换赋值
1.解构赋值
若对象options = {key1: value1, key2:value2, key3:value3}
则可以通过以下语句一次性拿到options内部三个值
let {key1, key2, key3} = options //注意:变量名必须与键名一模一样
2.交换赋值
顾名思义,就是将两个变量的值交换。以前需要写3句,ES6只需1句。
[a, b] = [b, a]
三. then与promise
1.then
使用jQuery的ajax函数时,可以将参数对象的函数(sucess,failure)用then传入。
then的语法:
xxx(yyy).then(resolve, reject)
- then两个参数都是函数
- then的参数是有顺序的,前者是上层函数成功时调用,后者是失败时调用
- then可以链式调用,每次调用都以上次调用同一函数的返回值为参
2.Promise
Promise是window的一个全局函数,是构造then的关键。
语法:
Promise(function(resolve, reject) {}
- Promise的参数是一个函数,而这个函数又以两个函数为参
- 添加套路:
xxx = function (yyy) {
return new Promise(function(resolve, reject) {/*code here*/})
}
四. 手写一个(jQuery版)ajax
这里从上一篇文章的原生版ajax出发,利用本文提到的三个技巧逐步优化,改成jQuery风格的ajax
//原生js版ajax
let xhr = new XMLHttpRequest()
xhr.open('POST', '/pay')
xhr.setHeader('content-type', 'application/json')
xhr.setHeader('sm', '18')
xhr.onreadystatechange = function () {
if(xhr.status === 4) {
if(xhr.readyState >= 200 && xhr.readyState < 300) {
console.log(xhr.responseText)
}else if(xhr.readyState >= 400) {
console.log('fail to request')
}
}
}
xhr.send('body')
//api版ajax
let $.ajax = function (method, url, headers, body, success, failure) {
let xhr = new XMLHttpRequest ()
xhr.open(method, url)
for(let key in headers) {
value = headers[key]
xhr.setHeader(key, value)
}
xhr.onreadystatechange = function () {
if(xhr.status === 4) {
if(xhr.readyState >= 200 && xhr.readyState < 300) {
console.log(xhr.responseText)
}else if(xhr.readyState >= 400) {
console.log(xhr)
}
}
}
xhr.send(body)
}
//改进1: 使用对象传参而非参数表
let $.ajax = function (options) {
let method = options.method
let url = options.url
let headers = options.headers
let body = options.body
let success = options.success
let failure = options.failure
/*同api版代码*/
}
//对应调用形式
$.ajax({
method: 'POST',
url: '/pay',
headers: {
'content-type' : 'application/json',
'sm' : '18'
},
body: 'body'
success: function (xhr) {
console.log(xhr.responseText)
},
failure: function (xhr) {
console.log(xhr)
}
})
//改进2:使用解构赋值简化代码
let $.ajax = function ({method, url, headers, body, success, failure}) {
/*同api版代码*/
}
//改进3:使用Promise和then将两个函数分离出去
//定义
let $.ajax = function ({method, url, headers, body}) {
return new Promise (function (resolve, reject)) {
...
if(xhr.status >= 200 && xhr.status < 300) {
resolve.call(undefined, xhr.responseText)
}else if (xhr.status >= 400) {
reject.call(undefined, xhr)
}
...
}
}
//对应调用形式
$.ajax({
method: 'POST',
url: '/pay',
headers: {
'content-type' : 'application/json',
'sm' : '18'
},
body: 'body'
}).then(success, failure)
let success = (xhr) => {console.log(xhr.responseText)}
let failure = (xhr) => {console.log(xhr)}
五. 其他小知识
1.前端中文文档集合(上哪找文档?)
2.一个函数如何接受两种参数个数?(参数个数的重载)
比如:函数f可以这样调用f(var1),也可以f(var1, var2)
a : 很简单,判断arguments.length即可
function f() { //这里可以不给参数
let var1
let var2
if(arguments.length === 1) {
var1 = arguments[0]
} else if (arguments.length === 2) {
var1 = arguments[0]
var2 = arguments[1]
}
}
3.XHR设置请求与获取响应
设置请求:
第一部分: xhr.open('get', '/xxx')
第二部分: xhr.setHeader('content-type', 'x-www-form-urlencoded')
第四部分: xhr.send('a=1&b=2')
获取响应:
第一部分: xhr.status / xhr.statusText
第二部分: xhr.getResponseHeader() / xhr.getAllResponseHeaders()
第四部分: xhr.responseText
暂无评论