js异步,宏任务微任务

异步模式

首先Javascript是单线程模式,即多任务需要排队执行。容易阻塞照成页面假死。为了解决这个问题所以有了异步。

单线程:指浏览器中执行avascript代码的线程只有一个。但浏览器的渲染进程(GUI)提供了多个线程。如JS引擎线程,事件触发线程,定时触发器线程,异步Http请求线程 

js引擎线程向下执行期间,如(setTimeout放入定时器出发线程,Http请求放入异步Http请求线程 ...),使得后面的代码继续执行,如此便实现了非阻塞。

异步模式:通过回调函数(callback)事件监听 发布/订阅  Promises对象等方式实现。其本质都是通过回调函数来实现异步代码的存放与执行。每一个异步都存在一个或则多个回调函数,这里异步执行完成之后马上出发回调函数,而下一个任务也不会等待回掉函数执行完成再执行。

1.回调

一个函数执行完毕后,得到想要的特定数据后在去执行的函数。

异步回调

function fnA(callback){
    setTimeout(()=>{
        callback('张三')
    },3000)
}
function fnB(name){
    console.log(name)
}
function fnC(){
    console.log('来了老弟')
}
fnA(fnB)
fnC()

执行结果:先来了老弟,后张三

同步回调

function fnA(callback) {
    for (let i = 0; i < 999999999; i++) {
        if(i===999999991){
            callback('张三')
        }
    }
    
}

function fnB(name) {
    console.log(name)
}

function fnC() {
    console.log('来了老弟')
}
fnA(fnB)
fnC()

执行结果:先张三后来了老弟。

回调与同步或者异步并无太大关系,因为我们既可以同步回调,也可以异步回调。

2.事件监听

采用事件驱动模式。任务的执行不取决代码的顺序,而取决于某一个事件是否发生。监听函数有:on,bind,listen,addEventListener,observe

3.观察者模式(发布/订阅)

4.promise对象(promise 模式)

promise存在三种状态,等待(pendding),失败(fulfilled),成功(rejected),且状态变化不可逆。当状态非pendding时,通过successCallback成功回调或者failCallback失败回调返回对应的结果。

EventLoop 事件环和消息队列

EventLoop是一种循环机制 ,不断去轮询一些队列 ,从中找到 需要执行的任务并按顺序执行的一个执行模型。

消息队列是用来存放宏任务的队列, 比如定时器时间到了, 定时间内传入的方法引用会存到该队列, ajax回调之后的执行方法也会存到该队列。

function fnA(){
    //操作
    console.log('fnA')
}
fnA()
setTimeout(()=>{
    //操作
    console.log('定时器')
},0)
//某ajax请求操作
function fnB(){
    for(let i=0;i<999999999;i++){
        if(i===999999991){
            console.log('fnB')
        }
    }
}
fnB()

以上面代码为列,执行结果为 fnA,fnB,定时器

这里js引擎栈会维持一个执行栈(call stack),js同步代码压入执行栈中生成匿名函数anonymous。同步代码执行完成之后,函数依次出栈。直至执行栈清空。

当js引擎遇到异步代码会交给相应的线程(web apis)去执行,直到(如:计时器时间到回调,电点击事件出发回调,或者网络请求完成回调等等),然后由事件循环(event loop)将这些回调依次放入消息队列(queue)。

这里事件循环(event loop)负责监听执行栈与消息队列,当执行栈为空时,从消息队列中依次取出异步回调放入执行栈。

 当执行栈(call stack)即js引擎线程空置的时候,事件触发线程按照先入先出的原则,将消息队列中的异步回调放入执行栈(call stack)中执行。

所以看似fnB执行耗时长于settimeout,但是fnB任然先执行完成。

宏任务和微任务

 宏任务可以理解为每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。

浏览器为了让 JS 内部宏任务 与 DOM 操作能够有序的执行,会在一个宏任务执行结束后,在下一个宏任务执行开始前,对页面进行重新渲染。

  宏任务包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、MessageChannel 等

  

微任务可以理解是在当前任务执行结束后需要立即执行的任务。也就是说,在当前任务后,在渲染之前,执行清空微任务。

  所以它的响应速度相比宏任务会更快,因为无需等待 UI 渲染。

  微任务包含:Promise.then、MutaionObserver、process.nextTick(Node.js 环境)等

这里同等级别下微任务优先于宏任务。

      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值