本文主要是介绍同步异步编程+promise全面解析+async/await,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
同步异步编程
首先,要从进程和线程中说起: 进程:一个程序[浏览器打开一个页面就是开辟一个进程] 线程:程序中具体做事情的 ( 一个进程中,会包含一到多个线程) 我们都知道,浏览器是多线程的:
GUI渲染线程:渲染页面的 JS引擎线程:渲染和解析JS的 时间触发线程:监听DOM事件的触发 定时器触发线程:监听定时器是否到时间 异步HTTP请求线程:从服务器端获取资源信息/数据的 WebWorker等等 然后呢,利用多线程是可以实现“异步编程 ”的:就是同时做多件事情 “同步编程 ”:单线程,一次只能处理一件事情,这件事情完成,才能继续处理后面的事情 JS是单线程的,因为浏览器只会分配一个“JS引擎线程”去渲染JS,所以JS大部分操作都是“同步的”+,但是JS中也一定会有一些“异步”的操作代码。 注意注意 :循环操作是同步编程:如果设置了死循环,当前循环这个事情永远都结束不了,后期所有的其他任务也都无法执行(避免出现死循环) 我们都知道JS代码是自上而下执行的,因此,浏览器解析的时候也是自上而下,而且遵循的原则是:同步永远先于异步,异步中同等可执行条件下,异步微任务永远先于异步宏任务。 说到这里,大家肯定会有疑问,异步微任务和宏任务都是什么,怎么区分呢?大家请看下图,这里面包含了常见的异步宏任务和微任务: 代码执行过程: @1 自上而下依次解析js代码,同步代码正常执行即可 @2 如果遇到异步代码,首先将该任务放入webAPI中进行状态监听,如果该任务此时可执行,不直接执行,而是放入EventQuene的可执行队列中去等待执行。 @2 EventQuene的可执行队列包含微任务和宏任务两个队列,则这时要对该任务进行区分,宏任务和微任务放入这两个队列中。 @3 然后继续执行下面的代码,等带所有同步代码执行完成后,再去EventQuene的可执行队列中去看,有微任务则拿出来执行,没有可执行的微任务再看可执行的宏任务。 @4 如果都没有,则继续等待,直至出现可执行的微任务/宏任务,继续按照规则执行,以此类推,直至代码执行结束。 然后一张代码图肯定就更加明白了
Promise全面解析
概念刨析 Promise可以说是一个内置类,可以通过new创建promise实例 let p=new Promise([executor]);
[executor]:可执行函数
new Promise的时候,在promise内部会立即把[executor]函数执行 同时给[executor]函数传递两个值[函数类型]:resolve/reject 内置私有属性 [[PromiseState]] 实例状态:pending准备状态 fulfilled/resolve成功态 rejected失败态 [[PromiseResult]] 实例的值 公共属性方法都是存在 Promise.prototype上的 then,catch,finally, Symbol(Symbol.toStringTag):“Promise” 其中[executor]执行resolve/reject都是为了改变promise实例的状态和值[结果],一旦状态被改变成fulfilled(成功态)/rejected(失败态)就不能再改为其他的状态,如果[executor]函数执行报错,则 [[PromiseState]]: rejected [[PromiseResult]]: 报错 因为Promise内部做了异常信息捕获利用[try/catch] THEN方法 不过实例状态的改变,可以控制,执行then方法时,存放的两个方法中的某一个方法执行 状态成功执行的是:onfulfilledCallback 状态失败执行的是:onrejectedCallback,并且把[[PromiseResult]]的值传递给方法。 同时,基于实例.then()执行返回的新实例的状态和值也是受原实例影响的,例如:原实例为p1,新实例为p2,则p2的状态和值取决于以下几个方面: P1.THEN存放的onfulfilled或者onrejected不论哪个方法执行 @1 看返回值 如果返回的是一个全新的promise实例[NEWP]:NEWP的状态和结果直接决定了P2的状态和结果 @2 如果返回的不是promise实例:只要方法执行不报错,P2就是成功的,方法return的结果就是P2的值。
Promise.all([Promise数组:{要求数组中的每一项尽可能都是promise实例}]):返回一个新的Promise实例AA,
// AA成功还是失败,取决于数组中的每一个promise实例是成功还是失败,
// 只要有一个是失败,AA就是失败的,只有都成功AA才是成功的片
async+await
我们都知道, async+await是为promise+generator的语法糖,在这里generator是生成器函数,就不做过多解释了,主要还是对async/awai~~t做主要说明: async:函数修饰符,控制函数返回promise实例
函数内部执行报错,则返回失败的promise实例,值是失败的原因 自己返回一个promise,以自己返回的为主~~ 如果函数内部做了异常捕获,则还是成功态 使用async的主要目的:是为了在函数内部使用await await: 后面放置一个promise实例[我们书写的不是,浏览器也会把其变为promise实例] ① await Promise.resolve(100); 已知实例状态是成功的 ② await new Promise.resolve((resolve,reject)=>{…});实例转态未知 ③ await 100; 等价于await Promise.resolve(100); ④await func();先把函数执行,把函数执行结果作为Promise实例放在await 后面 await会中断函数体中其下面的的代码执行{await表达式会暂停整个async函数的的执行进程并让出其控制权};只有等待await后面的promise实例是成功态以后,才会把之前暂停的代码继续执行,如果后面的promise实例是失败的,则下面的代码就不再执行了 await是异步的微任务 函数体中遇到await,后面的代码该咋就咋,但是下面的代码会暂停执行[把他们当做一个任务,放置在EventQuene的微任务队列中] 如下列例子:
function func1() {
console.log('func1 start');
return new Promise(resolve => {
resolve('OK');
});
}
function func2() {
console.log('func2 start');
return new Promise(resolve => {
setTimeout(() => {
resolve('OK');
}, 10);
});
}
console.log(1);
setTimeout(async () => {
console.log(2);
await func1();
console.log(3);
}, 20);
for (let i = 0; i < 90000000; i++) {} //循环大约要进行80MS左右
console.log(4);
func1().then(result => {
console.log(5);
});
func2().then(result => {
console.log(6);
});
setTimeout(() => {
console.log(7);
}, 0);
console.log(8);
// 1 4 func1 start func2 start 8 5 2 3 7 6
解析图如下 本期分享就到这里啦,欢迎大家留言讨论~~~&&小屋Niki
这篇关于同步异步编程+promise全面解析+async/await的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!