1. Promise Async
同步和异步
同步任务执行特点就是按顺序一个一个往下执行
如果中间加了类似settimeout定时器,他会带着后续的任务一起延迟,我们不希望后续任务被延迟,就产生了异步
常见的异步任务有两种:定时器和Ajax
异步任务创建之后不会像同步任务一样按顺序执行,而是在特殊队列里等待,然后通过一定的机制,添加到主线程中执行
console.log('任务1:...同步')
console.log('任务2:...同步')
setTimeout(() => {
console.log('任务3:....异步')
}, 0)
console.log('任务4:...同步')
这里可以看到,虽然时间设为0,但是setTimeout触发的异步任务内部的代码不会在它本来的位置执行
所以,异步任务可以理解为,他会在当前所有同步任务都执行完了之后再触发,和时间没关系
如果任务4需要依赖任务3处理的结果,这时就不能这么写了,应该把任务4也放到setTimeout里
console.log('任务1:...同步')
console.log('任务2:...同步')
setTimeout(() => {
console.log('任务3:...异步')
console.log('任务4:...同步')
}, 0)但是如果代码中有大量的异步任务参与程序执行,就会让代码出现大量嵌套层数
console.log('任务1:...同步')
console.log('任务2:...同步')
setTimeout(() => {
console.log('任务3:....异步')
console.log('任务4:...同步')
setTimeout(() => {
console.log('任务3:....异步')
console.log('任务4:...同步')
setTimeout(() => {
console.log('任务3:....异步')
console.log('任务4:...同步')
}, 0)
}, 0)
}, 0)就像这样,代码复杂程度大大提升,也没啥可读性
为了解决这个问题,产生了promise,用来解决异步写法中嵌套问腿
const p1 = new Promise((resolve, reject) => {
resolve('任务成功的结果')
// reject('任务失败的结果')
})
p1.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
})来分析一下这个代码,promise接收一个参数,这个参数是一个函数,而在这个函数里又接收两个形参
resolve和reject,resolve是成功时候的工具,而reject则是失败时候的工具
promise的实例对象具备三个方法,比较常用的是then和catch
then就是接下来做什么,在then里也可以接收一个回调函数,参数叫data,表示在成功的时候给我们传递的一个成功数据,也就是当promise里面是resolve时可以在里面传递信息,then就会被触发;比如说promise里是resolve时,then就会被触发,data接收resolve里的数据,然后执行
.catch就和then相反,它被reject触发,可以接收一个参数err,当promise里面是reject时,catch会被触发,err接收reject里的数据(里面可以写错误信息),然后执行(catch其实是reject的兜底操作,如果不写这个catch,当promise里是reject时,直接是报错,就像下图)

但是这也没解决嵌套问题啊?
其实可以在then里面再return new Promise
const p1 = new Promise((resolve, reject) => {
resolve('任务1成功的结果')
// reject('任务失败的结果')
})
p1.then(data => {
console.log(data)
return new Promise((resolve, reject) => {
resolve('任务2成功的结果')
})
})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
})其实可以这么理解,第一个任务执行成功之后,执行结果交给了第一个then,这时在第一个then里面再次return一个Promise,里面是第二个任务,这样return的执行结果会被下一个then接收,以此类推,就变成了执行完第一个执行第二个....但是中间也不会又太多嵌套,最多一层
如果想要让每个任务如果失败返回不一样的结果的话,就可以在每个then后面都加一个失败处理
先来一个错误案例
const p1 = new Promise((resolve, reject) => {
// resolve('任务1成功的结果')
reject('任务1失败的结果')
})
p1.then(data => {
console.log(data)
return new Promise((resolve, reject) => {
resolve('任务1成功的结果')
})
}, err => {
console.log('任务1失败了')
})
.then(data => {
console.log(data)
}, err => {
console.log('任务2失败了')
})就像这样,但是问题来了

任务1失败了,那任务2不应该也提示失败吗?为什么是undefined?
这个问题其实是在进行失败设置的时候,失败应该返回一个值,如果没有设置返回值,默认就会返回一个成功的promise对象,导致后续的then会被触发,但是接不到数据
这种问题又两种改法,一个是在err里返回一个新的Promise,这个Promise是一个失败状态;二是再err里抛出一个异常throw new Error( ),后面的看到前面已经失败了,后面的也就不干了
const p1 = new Promise((resolve, reject) => {
// resolve('任务1成功的结果')
reject('任务1失败的结果')
})
p1.then(data => {
console.log(data)
return new Promise((resolve, reject) => {
resolve('任务1成功的结果')
})
}, err => {
console.log('任务1失败了')
throw new Error('任务1失败')
})
.then(data => {
console.log(data)
}, err => {
console.log('任务2失败了')
})
这样其实就可以解决最开始层层嵌套的问题
const p1 = new Promise((resolve, reject) => {
resolve('阶段1执行成功')
//reject('任务1执行失败')
})
p1.then(data => {
console.log('任务1:...')
console.log('任务2:...')
console.log(data)
return new Promise((resolve, reject) => {
// resolve('阶段2执行成功')
reject('阶段2执行失败')
})
}, err => {
throw new Error('阶段1执行失败')
})
.then(data => {
console.log('任务3:...')
console.log('任务4:...')
console.log(data)
return new Promise((resolve, reject) => {
resolve('阶段3执行成功')
// reject('阶段3执行失败')
})
}, err => {
console.log(err)
throw new Error('阶段2执行失败')
})
.then(data => {
console.log('任务5:...')
console.log('任务6:...')
console.log(data)
}, err => {
console.log('阶段3执行失败')
})2. Async await
Async await就是基于Promise的语法糖,目的是用”看起来像同步的代码"去写异步的逻辑
先看Async,函数前面加上async后,就变成了异步函数,他有两个特点
1.返回值一定是一个Promise
2.赞函数内部可以使用await
先来看第一个特点
async function fn() {
return 123
}
const p = fn()
console.log(p)
这段代码和下面这段一样
function foo() {
return Promise.resolve(123)
}在看第二个特点之前先了解什么是await
await只能在async函数里用,作用是等待一个prmise完成并且拿到他的结果
先来看这一段
function asyncTask() {
return new Promise((resolve, reject) => {
//假装有一些关键代码
const isSuccess = true
if (isSuccess) {
resolve('任务1:....成功的处理结果')
} else {
reject('任务1:...失败的处理结果')
}
})
}
async function main() {
console.log('任务1')
const data = await asyncTask()
console.log(data)
console.log('任务3')
}
main()
可以看到他可以和同步操作一样,看起来没有区别,但实际上是异步操作逻辑
function stage1() {
return Promise.resolve('阶段1执行成功')
}
function stage2() {
return Promise.reject('阶段2执行失败')
}
function stage3() {
return Promise.resolve('阶段3执行成功')
}
async function run() {
try {
// 阶段1
const data1 = await stage1()
console.log('任务1:...')
console.log('任务2:...')
console.log(data1)
// 阶段2
const data2 = await stage2()
console.log('任务3:...')
console.log('任务4:...')
console.log(data2)
// 阶段3
const data3 = await stage3()
console.log('任务5:...')
console.log('任务6:...')
console.log(data3)
} catch (err) {
console.log('出错了:', err)
}
}
run()
可以看到,它的错误处理是配合try...catch进行书写
在实际开发中,async await最常用的就是请求接口
import axios from 'axios'
async function getArticles() {
try {
const res = await axios.get('/api/articles')
console.log('文章列表:', res.data)
} catch (err) {
console.log('请求失败:', err)
}
}
getArticles()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// console.log('任务1:...同步')
// console.log('任务2:...同步')
// setTimeout(() => {
// console.log('任务3:....异步')
// console.log('任务4:...同步')
// }, 0)
// const p1 = new Promise((resolve, reject) => {
// // resolve('任务1成功的结果')
// reject('任务1失败的结果')
// })
// p1.then(data => {
// console.log(data)
// return new Promise((resolve, reject) => {
// resolve('任务1成功的结果')
// })
// }, err => {
// console.log('任务1失败了')
// throw new Error('任务1失败')
// })
// .then(data => {
// console.log(data)
// }, err => {
// console.log('任务2失败了')
// })
// const p1 = new Promise((resolve, reject) => {
// resolve('阶段1执行成功')
// //reject('任务1执行失败')
// })
// p1.then(data => {
// console.log('任务1:...')
// console.log('任务2:...')
// console.log(data)
// return new Promise((resolve, reject) => {
// // resolve('阶段2执行成功')
// reject('阶段2执行失败')
// })
// }, err => {
// throw new Error('阶段1执行失败')
// })
// .then(data => {
// console.log('任务3:...')
// console.log('任务4:...')
// console.log(data)
// return new Promise((resolve, reject) => {
// resolve('阶段3执行成功')
// // reject('阶段3执行失败')
// })
// }, err => {
// console.log(err)
// throw new Error('阶段2执行失败')
// })
// .then(data => {
// console.log('任务5:...')
// console.log('任务6:...')
// console.log(data)
// }, err => {
// console.log('阶段3执行失败')
// })
function asyncTask() {
return new Promise((resolve, reject) => {
//假装有一些关键代码
const isSuccess = true
if (isSuccess) {
resolve('任务2:....成功的处理结果')
} else {
reject('任务2:...失败的处理结果')
}
})
}
async function main() {
console.log('任务1')
const data = await asyncTask()
console.log(data)
console.log('任务3')
}
main()
// async function foo() {
// return 123
// }
// const p = foo()
// console.log(p)
</script>
</body>
</html>