跳到主要内容

AJAX

let xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {

}
}

xhr.onprogress = function (event) {
if (event.lengthComputable) {
var complete = (event.loaded / event.total * 100 | 0);
progress.value = complete;
}
}
xhr.open('get', '/getInfo')
// 设置请求头
xhr.setRequestHeader()
// 超时控制
xhr.timeout =
xhr.ontimeout = function () {}
// 中止请求
xhr.abort()
// 发送请求
xhr.send()
readyState描述
0XHR已经创建,但未调用open()方法
1open()方法已经被调用
2send() 方法已经被调用
3正在接收响应的内容
4成功接收到响应

With Callback

const Ajax = ({
method = 'get',
url = '/',
data,
async = true
}, callback) => {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
let res = JSON.parse(xhr.responseText)
callback(res)
}
}
xhr.open(method, url, async)
if (method === 'get') {
xhr.send()
}
if (method === 'post') {
let type = typeof data
let header
if (type === 'string') {
header = 'application/x-www-form-urlencoded'
}
else {
header = 'application/json'
data = JSON.stringify(data)
}
xhr.setRequestHeader('Content-type', header)
xhr.send(data)
}
}

Ajax.get = (url, callback) => {
return Ajax({
url
}, callback)
}


Ajax.post = function (url, data, callback) {
return Ajax({
method: 'post',
url,
data,
}, callback)
}

Ajax.get('http://localhost:3000/getData', (res) => {
console.log(res)
})

With Promise

const Ajax = ({
method = 'get',
url = '/',
data,
async = true
}) => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
let res = JSON.parse(xhr.responseText)
resolve(res)
}
}
xhr.open(method, url, async)
if (method === 'get') {
xhr.send()
}
if (method === 'post') {
let type = typeof data
let header
if (type === 'string') {
header = 'application/x-www-form-urlencoded'
}
else {
header = 'application/json'
data = JSON.stringify(data)
}
xhr.setRequestHeader('Content-type', header)
xhr.send(data)
}
})
}

Ajax.get = (url) => {
return Ajax({
url
})
}



Ajax.get('http://localhost:3000/getData')
.then((data) => {
console.log(data)
})

With Generator

const Ajax = ({
method = 'get',
url = '/',
data,
async = true
}) => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
let res = JSON.parse(xhr.responseText)
resolve(res)
}
}
xhr.open(method, url, async)
if (method === 'get') {
xhr.send()
}
if (method === 'post') {
let type = typeof data
let header
if (type === 'string') {
header = 'application/x-www-form-urlencoded'
}
else {
header = 'application/json'
data = JSON.stringify(data)
}
xhr.setRequestHeader('Content-type', header)
xhr.send(data)
}
})
}

Ajax.get = (url) => {
return Ajax({
url
})
}


function* use() {
let data = yield Ajax.get('http://localhost:3000/getData')
console.log(data)
}

let obj = use()
obj.next().value.then((res) => {
obj.next(res)
})

With Generator + Co

const Ajax = ({
method = 'get',
url = '/',
data,
async = true
}) => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
let res = JSON.parse(xhr.responseText)
resolve(res)
}
}
xhr.open(method, url, async)
if (method === 'get') {
xhr.send()
}
if (method === 'post') {
let type = typeof data
let header
if (type === 'string') {
header = 'application/x-www-form-urlencoded'
}
else {
header = 'application/json'
data = JSON.stringify(data)
}
xhr.setRequestHeader('Content-type', header)
xhr.send(data)
}
})
}

Ajax.get = (url) => {
return Ajax({
url
})
}



function* use() {
let data = yield Ajax.get('http://localhost:3000/getData')
console.log(data)
}

co(use)

Co模块的原理类似如下

function co(gen){
var g = gen();

function next(data){
var result = g.next(data);
if (result.done) return result.value;
result.value.then(function(data){
next(data);
});
}

next();
}

With Async

其实async可以看成Generator + co的集成,不同的是关键字分别用async和await代替了*和yield,更加的语义化。除此之外,async函数会返回一个Promise对象。

const Ajax = ({
method = 'get',
url = '/',
data,
async = true
}) => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
let res = JSON.parse(xhr.responseText)
resolve(res)
}
}
xhr.open(method, url, async)
if (method === 'get') {
xhr.send()
}
if (method === 'post') {
let type = typeof data
let header
if (type === 'string') {
header = 'application/x-www-form-urlencoded'
}
else {
header = 'application/json'
data = JSON.stringify(data)
}
xhr.setRequestHeader('Content-type', header)
xhr.send(data)
}
})

}

Ajax.get = (url) => {
return Ajax({url})
}


async function use() {
let data = await Ajax.get('http://localhost:3000/getData')
console.log(data)
}

use()

补充一个常见的问题

async function A() { // 这代码一看就有问题
let arr = []
await fetch()
arr.forEach(async item => {
await fetch(item)
})
console.log(1)
}

async function A() { // 应该写成这样
let arr = []
let pArr = []
await fetch()
for (let item of arr) {
pArr.push(fetch(item))
}
const data = await Promise.all(pArr)
}

Axios

可以使用现成的AJAX库Axios,当然也可以采用下一节介绍的浏览器自带的Fetch来发请求

axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});