同步与异步-promise、async、await

236 阅读4分钟

JavaScript的单线程

js从诞生起就是单线程的,因为它的设计初衷是为了在浏览器中处理用户交互和DOM操作。如果js是多线程的,那么不同的线程可能会同时修改同一个DOM元素,从而导致不可预测的结果。单线程也有单线程的好处,可以避免竞态条件和死锁等并发问题,使得代码的编写和调试更加简单。


同步与异步

什么是同步?

同一个时间内,只能干一件事,因为js是单线程,所以js是同步的。同步的操作是严格按照先后顺序执行的,第一个操作没有执行完的话是不会执行第二个操作的。

function second() {
    console.log('second')
}
function first(){
    console.log('first')
    second()
    console.log('Last')
}
first()
​
打印结果:
firstsecondlast

什么是异步?

代码不会按照顺序依次执行,而是可以同时执行多个任务。在异步编程中,一段代码的执行不会阻塞其他代码的执行,因此可以提高程序的性能和响应速度。异步编程通常使用回调函数、Promise、async/await等技术实现。在JavaScript中,异步编程非常常见,例如通过ajax请求获取数据、读取文件等操作都是异步的。异步的操作不一定会按照先后顺序执行,碰到了比较耗时的操作时(例如等待网络请求的响应),不阻塞,而是接着执行后面的操作,等响应到达之后再执行刚才耗时操作的进一步处理。

const getList = () => {
    setTimeout(() => {
        console.log('我执行了!');
    }, 2000);
};
console.log('Hello World');
getList();
console.log('哈哈哈');
​
执行顺序是:
Hello World、哈哈哈、我执行了!(两秒以后执行最后一个)
​

宏任务与微任务

什么是宏任务?

宏任务(Macrotasks):js同步执行的代码块,setTimeout、setInterval、XMLHttprequest、setImmediate、I/O、UI rendering等。

什么是微任务?

微任务(Microtasks):promise、process.nextTick(node环境)、Object.observe, MutationObserver等。

浏览器执行的顺序(事件轮询:(2)(3)(4)(5)(6)执行的过程)

(1)执行主代码块,这个主代码块也是宏任务

(2)若遇到Promise,把then之后的内容放进微任务队列

(3)遇到setTimeout,把他放到宏任务里面

(4)一次宏任务执行完成,检查微任务队列有无任务

(5)有的话执行所有微任务

(6)执行完毕后,开始下一次宏任务


Promise

什么是Promise?

Promise是一种在JavaScript中处理异步操作的技术。它是一个对象,代表了一个尚未完成但最终会完成的操作。Promise有三种状态:pending(等待中)、fulfilled(已完成)和rejected(已拒绝)。当Promise处于pending状态时,代表操作尚未完成,当Promise被resolved(完成)时,代表操作已经成功完成,并返回一个值;当Promise被rejected(拒绝)时,代表操作失败,并返回一个错误。Promise通过链式调用(chaining)可以使异步操作更加清晰、易于管理和维护。

在JavaScript中,异步操作经常需要使用Promise来处理。Promise是一种用于处理异步操作的对象,它可以代表一个异步操作的最终完成或失败,并返回一个包含操作结果的值。通常,在需要等待某个异步操作完成后再执行一些操作的情况下,会使用Promise来处理。

例如,当需要从服务器获取数据时,可以使用Promise来处理异步操作。Promise对象可以表示获取数据的过程,当数据获取成功时,Promise对象会返回一个包含数据的值,而当获取数据失败时,Promise对象会返回一个错误信息。在使用Promise时,可以使用then()方法来处理获取数据成功时的操作,或者使用catch()方法来处理获取数据失败时的操作。

Promise.all

在需求开发中有遇到过这种场景,需要等待所有若干接口执行完后才进行下一步操作调下一个接口,这种情况,Promise.all就派上用场了

let getInfoA = new Promise((resolve, reject) => {
    console.log('小A开始执行了')
    resolve()
})
let getInfoB = new Promise((resolve, reject) => {
    console.log('小B开始执行了')
    resolve()
})
let getInfoC = new Promise((resolve, reject) => {
    console.log('小C开始执行了')
    resolve()
})
Promise.all([getInfoA, getInfoB, getInfoC]).then(res => {
   console.log('全都执行完了!')
})
​
//接收一个Promise对象组成的数组作为参数,当这个数组所有的Promise对象状态都变成resolved或者rejected的时候,它才会去调用then方法。

Promise是ES6用来解决异步的一个方法,目前比较广泛应用,axios就是用promise封装的。除了promise,ES6还提供了async、await,因为async、await使用的比较多。