同步异步和Event loop事件循环

目录

  • js 单线程模型
  • js 中的栈、堆和消息队列
    • 消息队列
  • Event Loop
    • 什么是事件循环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】,执行结束
  • 此时所有队列清空,事件循环结束。

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

原文地址:https://www.cnblogs.com/qiuqiubai/p/12545394.html

时间: 2024-10-29 13:40:03

同步异步和Event loop事件循环的相关文章

进程,线程,Event Loop(事件循环),Web Worker

线程,是程序执行流的最小单位.线程可与同属一个进程的其他线程共享所拥有的全部资源,同一进程中的多个线程之间可以并发执行.线程有就绪,阻塞,运行三种基本状态. 阮一峰大神针对进程和线程的类比,很是形象:计算机的核心CPU,是个工厂,时刻运转着,工厂里有很多个车间(进程),一个车间开工其他车间不能开工,就是说:单核CPU一次只能运行一个进程.任何时候,CPU总是运行一个进程. 而一个车间里面有很多工人(线程),协同完成一个任务.所以:一个进程可以包括多个线程.车间空间是工人共享的,一个进程中的内存空

nodejs所用的概念(同步,异步,事件驱动,事件循环等)通俗解释

1.回调:异步编程基本方法之一,当需要执行异步程序时候 ,一般采用后续传递,后续函数写入参数,逐层嵌套,使程序按期望方式走完流程2.异步: 每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的.异步的. js实现异步的方法:回调函数.事件监听.发布/订阅.Promises对象 ,有兴趣可以去阮一峰http://www.ruanyifeng.com/blog/

并发编程--一堆锁,GIL,同步异步,Event事件

目录 一堆锁 死锁现象(*****) 递归锁 RLock (了解) 信号量 (了解) GIL(*****) 什么时GIL锁 为什么需要GIL锁 Cpython解释器与GC的问题 GIL锁带来的问题 多线程与多进程性能对比 进程池与线程池 同步异步(*****) Event事件 一堆锁 死锁现象(*****) ? 死锁指的是,某个资源被占用之后,一直得不到释放,导致其他需要这个资源的线程进入阻塞状态 产生死锁的情况 对同一把互斥锁,进行了多次加锁 一个共享资源,在访问时必须具备多把锁,但是这些锁被

JavaScript 异步、栈、事件循环、任务队列

概览 我们经常会听到引擎和runtime,它们的区别是什么呢? 引擎:解释并编译代码,让它变成能交给机器运行的代码(runnable commands). runtime:就是运行环境,它提供一些对外接口供Js调用,以跟外界打交道,比如,浏览器环境.Node.js环境.不同的runtime,会提供不同的接口,比如,在 Node.js 环境中,我们可以通过 require 来引入模块:而在浏览器中,我们有 window. DOM. Js引擎是单线程的,如上图中,它负责维护任务队列,并通过 Even

asyncio:异步I/O、事件循环和并发工具(持续跟新中)

流畅的Python书中的协程部分版本太低,而且讲的比较少,这次根据Python3标准库书中实例来学习记录asyncio的使用. asyncio模块提供了使用次饿成构建并发应用的工具.threading模块通过应用线程并发,mutilprocessing使用系统进程实现并发,asyncio则使用一个单线程单进程的方法来实现并发,应用的各个部分会彼此合作,在最优的时刻显式地切换任务. asyncio提供的框架以一个事件循环(event loop)为中心,这是一个首类对象,负责高效地处理I/O事件.系

js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环中的同步任务,异步任务: 同步和异步任务在不同的执行"场所",同步的进入主线程,异步的进入Event Table执行并注册函数. 当指定的异步事情完成时,Event Table会将这个函数移入Event Queue. 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,推

从一个例子引发对JS运行机制之 Event Loop 的思考

栗子如下: for (var i = 0; i < 5; i++) { setTimeout(function() { console.log('i: ',i); //一秒之后输出几乎没有时间间隔依次输出5个5 }, 1000); } console.log(i); //立即输出5 想必很多人看到立马能看出答案吧,但是为什么定时器不能依次打印出1,2,3,4,5呢?答案稍后分晓. 那到底怎么才能依次输出我们想要的结果呢?大家可能都想到是利用闭包,或者是利ES6中的let声明,但是今天我们不讲这个

javascript的执行机制—Event Loop

既然今天要谈的是javascript的事件循环机制,要理解事件循环,首先要知道事件循环是什么. 我们先从一个例子来看一下javascript的执行顺序. <script> setTimeout(function() { console.log('定时器开始了.'); },0) new Promise(function(resolve) { console.log('马上执行for循环了'); for (let i = 0; i < 10000; i++) { i == 99 &&

深入理解JavaScript事件循环机制

前言 众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. Ther