Promise
为了解决回调地狱,就要使用 promise 语法
语法:
new Promise(function (resolve, reject) {
// resolve 表示成功的回调
// reject 表示失败的回调
}).then(function (res) {
// 成功的函数
}).catch(function (err) {
// 失败的函数
})
每一个异步事件,在执行的时候都会有三个状态,执行中 / 成功 / 失败,
因为它包含了成功的回调函数
所以我们就可以使用 promise 来解决多个 ajax 发送的问题
new Promise(function (resolve, reject) {
ajax({
url: '第一个请求',
success (res) {
resolve(res)
}
})
}).then(function (res) {
// 准备发送第二个请求
return new Promise(function (resolve, reject) {
ajax({
url: '第二个请求',
data: { a: res.a, b: res.b },
success (res) {
resolve(res)
}
})
})
}).then(function (res) {
ajax({
url: '第三个请求',
data: { a: res.a, b: res.b },
success (res) {
console.log(res)
}
})
})
注:
Promise的任务队列为微任务队列,优先级高于宏任务队列,次于同步队列,会在事件循环之后执行
当Promise赋值变量传递给另一个Promise的reslove()时,状态会进行传递
Promise状态不可逆,Promise传递了状态 then才会执行否则会一直等待,Promise写两个状态只执行第一个,一旦确定了状态就不能修改
then、catch也是一个Promise,是对上一个Promise的结果处理,then、catch默认返回结果是成功,
then如果return的是一个值那下一个then就能相应接收,如果then返回的是一个new Promise,那下一个then就是对这个返回的new Promise的状态处理(没有状态则下一个then一直等待)
then如果return的也是then,那这个返回出来的then可以封装为Promise,跟Promise性质一样
catch
Promise内会进行错误处理,没有改变Promise的状态下,throw new Error(“fail”)或hd+1(hd未定义等其他错误) 都会判断为reject进行处理同时执行处理错误的回调函数。
这个错误也可以使用.catch()进行捕获,会捕获之前所有then的错误 所以可以在前面的then省略错误处理回调,在Promise的最后添加.catch(()=>{})统一进行错误处理
finally
写在Promise的最后不管状态成功失败都会执行.finally(()=>{})
reslove
Promise.reslove() 直接为成功状态
reject
Promise.reject() 直接为失败状态,也可以通过抛异常的方式改变单次Promise的状态
all
Promise.all([第一个Promise,第二个Promise]) .then()
如果前面的Promise都为成功状态才会执行Promise.all的then下的成功回调
allSettled
Promise.allSettled([第一个Promise,第二个Promise]) .then()
会把前面成功跟失败的promise全部收集起来,Promise.allSettled的状态始终是成功状态
race
Promise.race([第一个Promise,第二个Promise]) .then()
比较几个Promise那个先执行完 ,then获取那个Promise的reslove(“获取值”)
// 手写promise
class MyPromise {
constructor(executor) {
this.status = 'pending' // 初始状态为等待
this.value = null // 成功的值
this.reason = null // 失败的原因
this.onFulfilledCallbacks = [] // 成功的回调函数数组
this.onRejectedCallbacks = [] // 失败的回调函数数组
let resolve = value => {
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn()) // 调用成功的回调函数
}
}
let reject = reason => {
if (this.status === 'pending') {
this.status = 'rejected'
this.reason = reason
this.onRejectedCallbacks.forEach(fn => fn()) // 调用失败的回调函数
}
};
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.status === 'fulfilled') {
setTimeout(() => {
const x = onFulfilled(this.value);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
})
}
if (this.status === 'rejected') {
setTimeout(() => {
const x = onRejected(this.reason)
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
})
}
if (this.status === 'pending') {
this.onFulfilledCallbacks.push(() => { // 将成功的回调函数放入成功数组
setTimeout(() => {
const x = onFulfilled(this.value)
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
})
})
this.onRejectedCallbacks.push(() => { // 将失败的回调函数放入失败数组
setTimeout(() => {
const x = onRejected(this.reason)
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
})
})
}
})
}
}
// 测试
function p1() {
return new MyPromise((resolve, reject) => {
setTimeout(resolve, 1000, 1)
})
}
function p2() {
return new MyPromise((resolve, reject) => {
setTimeout(resolve, 1000, 2)
})
}
p1().then(res => {
console.log(res) // 1
return p2()
}).then(ret => {
console.log(ret) // 2
})
Async/Await
async/await
是一个 es7 的语法,是 回调地狱的终极解决方案
语法:
async function fn() {
const res = await promise对象
}
await 一个 promise 对象,可以把异步代码写的看起来像同步代码
await会将后面代码挂起 等待await后面的promise返回状态 这个称为协程
只要是一个 promiser 对象,那么就可以使用 async/await
来书写
async function fn() {
const res = new Promise(function (resolve, reject) {
ajax({
url: '第一个地址',
success (res) {
resolve(res)
}
})
})
// res 就可以得到请求的结果
const res2 = new Promise(function (resolve, reject) {
ajax({
url: '第二个地址',
data: { a: res.a, b: res.b },
success (res) {
resolve(res)
}
})
})
const res3 = new Promise(function (resolve, reject) {
ajax({
url: '第三个地址',
data: { a: res2.a, b: res2.b },
success (res) {
resolve(res)
}
})
})
// res3 就是我们要的结果
console.log(res3)
}
注:
async中没有await就是同步代码
async中有await就是异步代码