• 同步异步和Event loop事件循环


    js 单线程模型

    JavaScript 是单线程、非阻塞的一种语言,只有一个主线程,同时只能执行一个任务。

    js 使用单线程是为了简单化

    js 中的栈、堆和消息队列

    存放的是调用函数的记录——调用帧

    存放的是对象

    消息队列

    • 包含待处理消息的队列
    • 每个消息都关联了一个回调函数,用以处理这个消息。

    Event Loop

    什么是事件循环Event Loop

    Event Loop 是一种循环检查机制

    • 当主线程的任务执行完以后,就会去消息队列查看是否有满足条件的异步任务(js 将在消息队列中的任务称为异步任务)。
    • 如果有,就将该异步任务调入主线程成为同步任务,然后执行其关联的回调函数
    • 然后不断循环,如果任务队列的任务全部执行完了,那么程序就结束。

    主线程

    同步任务和异步任务

    同步任务

    是没有被挂起,在主线程里排队执行的任务

    异步任务

    分为宏任务和微任务

    宏任务

    包括:
    包括整体代码 script、setTimeout、setInterval、setImmediate、I/O、UI rendering

    微任务

    包括:
    promise.then, process.nextTick(node中)

    宏任务的执行顺序在微任务之前

    事件循环的过程

    任务执行时,首先执行整体代码这个【宏任务】,将主线程同步任务清空之后,检查微任务列表,如果不为空则逐个加入到主线程进行执行;微任务列表清空以后,执行宏任务,如果宏任务执行完一个以后微任务列表不为空了,那么接着执行微任务,直到微任务清空,再执行宏任务,这样一直循环到所有的任务列表清空,事件循环结束。

    示例:

    console.log(1); //1.同步任务#1
    setTimeout(function(){  //1.宏任务加入marcotask $1
        console.log(2);
        new Promise(function(resolve){ 
            console.log(3);
            setTimeout(function(){  //$3
                console.log(4);
            });
            resolve();
        }).then(function(){ //&2
            console.log(5);
        });
    });
    new Promise(function(resolve){  //1.promise 是同步任务!!!#2
            console.log(6);
            setTimeout(function(){  //1.加入宏任务队列 $2
                console.log(7);
            });
            resolve();
        }).then(function(){ //1.微任务加入microtask &1
            console.log(8);
        });
    console.log(9); //1.同步任务#3
    

    结果为 1 6 9 8 2 3 5 7 4

    • 首先执行同步任务 #1,遇到 setTimeout 宏任务 $1 加入到 macrotask 队列,遇到 promise 为同步任务 #2,直接执行,promise 执行遇到 setTimeout 宏任务 $2,加入 macrotask 队列,遇到 then() &1 加入微任务队列,然后执行同步任务 #3,第一次事件循环结束;
      此时:输出了结果 【1 6 9】
      macrotask:$1 $2
      microtask:&1
    • 执行微任务 &1,执行同步任务输出【8】,微队列清空,执行宏任务
    • 执行宏任务 $1,执行同步任务输出 【2】,遇到 promise 执行其同步任务,输出【3】,遇到 setTimeout 宏任务 $3,加入 macrotask,遇到 then() &2,加入 microtask$1 宏任务执行完毕,microtask 不为空,所以接下来执行微任务。
    • 执行微任务列表的任务:&2,输出 【5】,结束后微队列清空,执行宏任务
    • 执行 $2 宏任务,输出 【7】,执行结束
    • 执行 $3 宏任务,输出 【4】,执行结束
    • 此时所有队列清空,事件循环结束。

    总结:先执行一个宏任务,再执行之下的所有微任务,如此循环;

  • 相关阅读:
    一个生日的类,一个人的类(上课)
    c语言菜单框架
    Latex Algorithm 语法错误导致无法编译
    CDQ WQS Rush
    Dinic Rush
    String Rush
    计算几何 学习笔记
    DP Rush
    Graph Rush
    Data Rush EZ ver.
  • 原文地址:https://www.cnblogs.com/qiuqiubai/p/12545394.html
Copyright © 2020-2023  润新知