同步异步为什么存在
JS是一个单线程的语言。
为什么?
因为JS是可以去操作DOM的,假设JS设计成一个多线程语言,主线程再给DOM的innerHtml做一个赋值操作,另一个线程把这个DOM结构删除了,这肯定不可以,哪怕后期出了一个web worker 也是不允许操作DOM的
但是浏览器加载一些图片资源、ajax。或者轮训的内容,时间长,会阻塞后续操作,于是出现了异步
定时器
xxxxxxxxx(一堆不确定的代码)
setTimeout(()=>{console.log(111)},500);
上面代码块做了什么?
- 遇见定时器后,将定时器内的函数进行注册,也就是放入Event Table
- 500ms后将Event Table内注册的函数放入 Event queue
- 若主线程call stack为空
- 将Event queue按顺序的放入call stack中进行执行
- 不为空不执行第四步
宏任务和微任务
setTimeout(()=>{console.log(111)},0)
let promise = new Promise((resolve,reject)=>{
console.log(222);
resolve(3333)
});
let promise2 = new Promise((resolve,reject)=>{
console.log(555);
resolve(6666)
});
setTimeout(()=>{
console.log(4444);
},0)
promise.then(res=>{
console.log(res);
});
promise2.then(res=>{
console.log(res);
});
常见的宏任务:setTimeout、setInterval(定时器类)
常见的微任务:promise process.nextTick(一个node环境的方法)。
执行规则
- call stack中的内容执行完毕清空
- Event queue检查一下哪些是宏任务哪些是微任务
- 执行所有的微任务
- 执行一个宏任务
- 之后再次执行所有的微任务
终于到了Promise
Promise 是异步编程的一种解决方案,
从语法上讲,promise是一个对象,从它可以获取异步操作的消息;
从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。
promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态) ;状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
promise是用来解决两个问题的:
- 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
- promise可以支持多个并发的请求,获取并发请求中的数据
- 这个promise可以解决异步的问题,本身不能说promise是异步的
Promise用法
Promise是一个构造函数,自己身上有all、reject、resolve方法,原型上有then、catch等方法。
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log('执行完成');
resolve('我是成功!!');
}, 2000);
});