AJAX
1. 介绍
AJAX,是 Asynchronous JavaScript And XML,意思是利用JavaScript执行异步网络请求,对页面进行局部更新,而不需要重载页面。
AJAX是浏览器的功能,利用浏览器在window上增加的XMLHttpRequest函数,利用该函数构造出一个对象,使用该对象进行请求发送与响应接受。
2. 使用
- 创建一个
XMLHttpRequest
对象 - 调用对象的
open
方法启用。 - 监听对象的
onreadystatechange
事件(或者是onload
和onerror
事件),处理函数对返回的数据进行处理。 - 调用对象的
send
方法发送请求。
完整版:
var request = new XMLHttpRequest()
request.open('GET','/xxx')
request.onreadystateChange = function(
if(request.readyState === 4){
console.log('请求完成')
if(request.responese.status >= 200 && request.response.status < 300){
console.log('请求成功')
}else{
console.log('请求失败')
}
}
)
request.send()
复制代码
简略版:
var request = new XMLHttpRequest()
request.open('GET','/xxx')
request.onload = ()=>{console.log('请求成功')
request.send()
复制代码
3. onreadystatechange
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | 代理被创建,但尚未调用 open() 方法。 |
1 | OPENED | open() 方法已经被调用。 |
2 | HEADERS_RECEIVED | send() 方法已经被调用,并且头部和状态已经可获得。 |
3 | LOADING | 下载中; responseText 属性已经包含部分数据。 |
4 | DONE | 下载操作已完成。 |
创建 -> 打开 -> 发送 -> 接收 -> 完成
每一次state的改变都会触发readystatechange事件,但我们一般只关心state为4的阶段,此阶段数据接收已完成,可来进行数据处理。onload函数也会在请求完成后即state为4的时候调用。
终止请求
使用XHR对象的abort方法会终止该请求,state会被重置为0。
Promise
1. 介绍
Promise是在ES6中确定的对异步及回调处理的规范实现。
一个 Promise 必然处于以下几种状态之一:
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled): 意味着操作成功完成。
- 已拒绝(rejected): 意味着操作失败。
2. 使用Promise封装ajax
关键:return new Promise((resolve, reject)=>{...})
用以返回一个Promise对象。
ajax = (method, url) => {
return new Promise((resolve, reject)=>{ //关键,用以返回一个Promise对象
var request = new XMLHttpRequest()
request.open(method, url)
request.onreadystateChange = function(
if(request.readyState === 4){
console.log('请求完成')
if(request.responese.status === 200){
console.log('请求成功')
resolve.call(null, request.response) //成功则调用resolve
}else{
console.log('请求失败')
reject.call(null, request) //失败则调用reject
}
}
)
request.send()
})
}
复制代码
3. then / catch / finally 函数
一个Promise对象具有then函数,then函数接受两个函数,第一个函数当 Promise 变成接受状态(fulfilled)时被调用,第二个函数当 Promise 变成拒绝状态(rejected)时被调用。
catch 接收一个函数,在Promise被reject的时候执行,除非该函数抛出错误或返回一个失败的Promise,否则返回的Promise一直是resolved。实质上catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。
finally接收一个回调函数,在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定该回调函数。这避免了同样的语句需要在then()和catch()中各写一次的情况。
以调用上面封装的ajax函数为例
ajax('GET','/user')
.then(
res=> console.log(res),
request => console.log(request)
)
.catch(err => console.log(err))
.finally( () => console.log('结束') )
复制代码
4. all / race / any 函数
-
对比小结:
- 都接受一个可迭代对象
- all:全resolve才resolve,任何一个reject则reject
- race:任何一个resolve或reject,则返回其状态
- any:任何一个resolve,则成功。全为reject,则reject。
-
Promise.all(iterable)
返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]).then((values) => { console.log(values); }); // expected output: Array [3, 42, "foo"] 复制代码
-
Promise.race(iterable)
当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); Promise.race([promise1, promise2]).then((value) => { console.log(value); // Both resolve, but promise2 is faster }); // expected output: "two" 复制代码
-
Promise.any(iterable)
接收一个Promise对象的集合,当其中的一个 promise 成功,就返回那个成功的promise的值。
const pErr = new Promise((resolve, reject) => { reject("总是失败"); }); const pSlow = new Promise((resolve, reject) => { setTimeout(resolve, 500, "最终完成"); }); const pFast = new Promise((resolve, reject) => { setTimeout(resolve, 100, "很快完成"); }); Promise.any([pErr, pSlow, pFast]).then((value) => { console.log(value); // pFast fulfils first }) // 期望输出: "很快完成" 复制代码
async / await
- 介绍
async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。 复制代码
async声明一个函数为异步执行的,await则是等待一个异步方法执行完成。
async函数一定会返回一个promise对象。如果一个async函数的返回值看起来不是promise,那么它将会被隐式地包装在一个promise中。
await后面的代码可近似认为是在promise的then的回调的,多个await相当于链式调用多个then。
使用async / await,则无需使用promise.then传递回调函数。在await之后的代码会等待结束后继续执行,错误处理使用try…catch..
以下代码实现的功能等价:
- 使用Promise
ajax('GET','user').then((res)=>console.log(res), (err)=>console.log(err))
复制代码
- 使用async / await
async xxx(){
try{
let result = await ajax('GET','user')
console.log(result)
}catch(err){
console.log(error)
}
}
xxx()
复制代码