天天看点

ajax success function_手写一个(jQuery版)ajax

手工实现 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)

这时可以考虑把参数打包成有结构的对象,传一个对象参数

使用对象传参的好处。一是逻辑明确,不必考虑哪个参数是在哪个位置,参数对应关系直接从键值对解析即可。二是扩展简单。

细节:使用对象传参的时候,习惯上形式参数取名为options

2.效果:

before:多个参数传入

ajax success function_手写一个(jQuery版)ajax

after:一个对象传入

ajax success function_手写一个(jQuery版)ajax
二、ES6语法:解构赋值与交换赋值

1.解构赋值

若对象options = {key1: value1, key2:value2, key3:value3}

则可以通过以下语句一次性拿到options内部三个值

let {key1, key2, key3} = options  //注意:变量名必须与键名一模一样
           
ajax success function_手写一个(jQuery版)ajax

示例

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可以链式调用,每次调用都以上次调用同一函数的返回值为参
ajax success function_手写一个(jQuery版)ajax

then链式调用

2.Promise

Promise是window的一个全局函数,是构造then的关键。

语法:

Promise(function(resolve, reject) {}
           
  • Promise的参数是一个函数,而这个函数又以两个函数为参
  • 添加套路:
xxx = function (yyy) {
return new Promise(function(resolve, reject) {/*code here*/})
}
           
  • 只需将原代码写入,并给出resolve和reject的调用时机,即可实现then功能
四、手写一个(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.前端中文文档集合(上哪找文档?)

cndevdocs.com

ajax success function_手写一个(jQuery版)ajax
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