JS异步编程——Event Loop事件循环及发布订阅

文章目录

  • 前言
  • 一、理解异步
    • 1. 学习资料链接
    • 2. 同步函数 vs 异步函数
      • 1. 同步函数
      • 2. 异步函数
  • 二、Event Loop事件循环
    • 1. 学习资料链接
    • 1. 浏览器环境下JS引擎的代码执行
    • 2.事件队列 Task Queue
    • 3. 微任务与宏任务
    • 4. 简述事件循环闭环流程
  • 三、异步编程-发布订阅
    • 1. 异步处理线程
    • 2. 异步编程解决方案(回调地狱)
      • 2.1. 发布/订阅
        • 2.1.1 发布/订阅模式
        • 2.1.2 观察者模式
      • 2.2. deferred对象
      • 2.3. Promise
      • 2.4. Generator
      • 2.5. async/await
  • 总结


前言

在JavaScript中,异步是一个重要的内容,该篇从基础的进程、线程开始,系统的了解异步。


一、理解异步

	先浏览学习资料,对进程、线程和浏览器中的进程线程有一定的认识。

1. 学习资料链接

序号 资料名称 链接 备注
1 官方图解:Chrome 快是有原因的,现代浏览器的多进程架构! https://juejin.im/post/5bd7c761518825292d6b0217 学习这篇文章可以了解浏览器的架构以及每个模块负责的工作,宏观上了解浏览器的工作原理。
2 进程与线程的一个简单解释 https://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 文章生动形象的比喻了进程和线程,将抽象的概念形象化了
3 浏览器进程?线程?傻傻分不清楚! https://imweb.io/topic/58e3bfa845e5c13468f567d5 重点讲解线程、进程的区别,以及浏览器内核的多线程
4 定时器标准 https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers 规范对定时器的说明

2. 同步函数 vs 异步函数

1. 同步函数

	如果一个函数是同步执行,那么当这个函数被调用时不会立即返回,只有当该函数要做的事情全部执行完,才会返回。
	同步函数处理机制:
		当一个线程调用一个同步函数时(例如:该函数用于完成写文件任务),如果该函数没有立即完成规定的操作,则该操作会导致该调用线程的挂起(将CPU的使用权交给系统,让系统分配给其他线程使用),直到该同步函数规定的操作完成,该调用线程才会被重新调度。
	阻塞:由于在浏览器系统中,JavaScript是单线程的([学习资料3-浏览器进程·线程](https://imweb.io/topic/58e3bfa845e5c13468f567d5)),如果调用同步函数的线程被挂起(也就是JS线程被挂起),只有等他执行完,JS线程才会重新获得CPU的使用权,继续向下执行。

2. 异步函数

	如果一个异步函数被调用,那么该函数会立即返回(尽管该函数要做的事情还没有做完,也会立即返回)。
	异步函数处理机制:
		当一个线程调用的是一个异步函数(例如:该函数用于完成写文件任务),该函数会立即返回尽管其规定的任务还没有完成,这样线程就会执行异步函数的下一条语句,而不会被挂起(异步函数所规定的工作通过另一个线程完成)。
		处理异步函数工作的线程可能是在异步函数中新创建的,也可能是系统中已经准备好的线程。

二、Event Loop事件循环

1. 学习资料链接

序号 资料名称 链接 备注
1 Event Loops标准 https://html.spec.whatwg.org/multipage/webappapis.html#event-loops 标准对Event Loops的说明
2 Node.js 事件循环,定时器和 process.nextTick() https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop 介绍了nodejs的事件循环和定时器
3 调用栈 https://developer.mozilla.org/zh-CN/docs/Glossary/Call_stack 介绍js运行调用栈
4 JS中的栈内存堆内存 https://juejin.im/post/5d116a9df265da1bb47d717b

1. 浏览器环境下JS引擎的代码执行

JS异步编程——Event Loop事件循环及发布订阅_第1张图片

2.事件队列 Task Queue

JS异步编程——Event Loop事件循环及发布订阅_第2张图片
在1.图代码中插入一个异步任务,那这个异步任务先加入到事件队列中(不会立即执行),等当前的执行栈中都执行完了,再依次执行事件队列中的任务,以此往复。

3. 微任务与宏任务

	在异步任务中又分为微任务和宏任务。
	宏任务:我们通常把宿主发起的任务称为宏观任务;
		1. setTimeout
		2. setInterval
		3. setImmediate (Node独有)
		4. requestAnimationFrame (浏览器独有)
		5. I/O
		6. UI rendering (浏览器独有)
	微任务: 把JavaScript引擎发起的任务称为微观任务(微任务将代码执行时机变得可控)。
		1. process.nextTick (Node独有)
		2. Promise
		3. Object.observe
		4. MutationObserver

JS异步编程——Event Loop事件循环及发布订阅_第3张图片

4. 简述事件循环闭环流程

	当执行栈为空时,执行一下步骤
	1. 执行微任务队列;
		a. 选择微任务队列中最早的任务(任务x);
		b. 如果任务x为空(意味着微任务队列为空),跳转到步骤(g);
		c. 将“当前正在运行的任务”设置为“任务x”;
		d. 运行“任务x”;
		e. 将“当前正在运行的任务”设置为空,删除“任务x”;
		f. 选择微任务队列中下一个最早的任务,跳转到步骤(b);
		g. 完成微任务队列;
	2. 选择宏任务队列中最早的任务(任务A);
	3. 将“当前正在运行的任务”设置为“任务A”;
	4. 运行“任务A”(表示运行回调函数)同步代码;
	5. 跳到第一步;
	6. 将“当前正在运行的任务”设置为空,删除“任务A”结束本次循环;
	7. 跳到第2步;

三、异步编程-发布订阅

1. 异步处理线程

JS异步编程——Event Loop事件循环及发布订阅_第4张图片
由上图可知,js中异步编程最原始的方法采用的是回调的方式。

2. 异步编程解决方案(回调地狱)

	*以同步的方式书写异步代码

2.1. 发布/订阅

2.1.1 发布/订阅模式

JS异步编程——Event Loop事件循环及发布订阅_第5张图片
发布订阅模式是完全解耦的,发布者、消息中心、订阅者三方的业务逻辑完全独立的,之间仅通过消息来传递。

2.1.2 观察者模式
在观察者模式中,被观察者(Subject)只需要一套观察者的集合(Observer),将有关状态的任何变更自动通知给观察者(watcher),这个设计是松耦合的。

JS异步编程——Event Loop事件循环及发布订阅_第6张图片
上图是Vue官方教程中的原图;Vue数据侦测观察者:https://cn.vuejs.org/v2/guide/reactivity.html

2.2. deferred对象

2.3. Promise

2.4. Generator

2.5. async/await


总结

	异步编程解决方案(回调地狱)的后边几种常用解决方案,将在后续章节中详细介绍。

革命尚未成功,同志仍需努力。

你可能感兴趣的:(前端进阶笔记,#,Javascript进阶,javascript,前端,开发语言)