js同步异步
Last updated on 8 months ago
什么是同步异步
同步编程
同步,指同一时序线、同一线程,多个操作按顺序进行,默认情况下,很多语言都是同步进行的,而当我们遇到执行较长的代码时,同步会让我们的程序造成阻塞
1
2
3
4
5
6
7
8// 定义一个阻塞函数
function sleep(milliSeconds){
var startTime = new Date().getTime()
while (new Date().getTime() < startTime + milliSeconds)
}
// 阻塞3s
sleep(3000)
console.log(123)执行,发现等待3s后,控制台才有输出。程序发生了阻塞
异步编程
同理,异步就是不在同一线程、时许线上,相当于俩边同时进行,但是我们知道,js是单线程的,单线程要怎么做到异步呢?
虽然js是单线程的,但浏览器不是,浏览器在接受到异步请求后会交给其他线程执行,执行完成后返回。
异步的实现方式
在js中异步有两种实现方式:
回调函数
比如
setTiemoUt()
函数,我们可以输入一个回调函数和一个时间作为参数,执行setTimeout()
的时候会立即返回,执行下方的代码,在计时结束后会返回回调函数1
2
3
4setTiemout(()=>{
console.log("我是回调")
},3000)
console.log("我会比回调先执行")回调函数非常简单好理解,但如果我们需要依次执行异步操作,就会被写成这样
1
2
3
4
5
6
7
8
9setTimeout(()=>{
console.log("等3s")
setTimeout(()=>{
console.log("再等3s")
setTimeout(()=>{
console.log("还等3s")
},3000)
},3000)
},3000)这种被称为函数瀑布,回调地狱,为了解决这个问题,ES6引入了promise类
Promise
直译为承诺,也就是先承诺,再通过回调兑现
1
2
3
4
5
6
7
8
9
10
11const promise = new Promise((resolve, reject)=>{
// 异步操作
resolve("成功信息")
reject("错误信息")
}).then((result)=>{
// 操作成功后
}).catch((error)=>{
// 操作失败后
}).finally(()=>{
// 无论成功失败都会调用
})Promise
的构造函数接受一个回调函数作为参数,回调函数的参数有两个:resoleve
和reject
在promise中,**一定要调用
resolve()
或reject()
**,resolve()
用于返回成功信息,reject()
用于返回错误信息,在执行后会对应的进入到then()
方法或catch()
方法,如果不写,promise会一直处于pending
等待状态Promise
的方法有- then():用于处理成功状态的回调
- catch():用于处理失败状态的回调
- finally():无论成功失败都会执行的回调
而对于上面的回调地狱,promise提供了promise链来实现,将左右方向延申变为了上下方向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("3s");
resolve();
}, 3000);
})
.then(() => {
// 返回一个promise对象
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("又3s");
resolve();
}, 3000);
});
})
.then(() => {
setTimeout(() => {
console.log("还3s");
}, 3000);
});
console.log("他们是异步,我是第一个执行的");async/await语法糖
这是基于
Promise
的语法糖,通过async
关键字可以将函数标记为异步函数1
2
3async function() {
}而
await
关键字用于async
内部,用于等待另一个promise
函数1
2
3
4
5
6
7
8
9
10const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
async function ff() {
await delay(3000);
// 等待上面异步结束后才执行
console.log("3s过去了");
}
ff();
console.log("我最先执行");