同步和异步程序的关联和区别是?Guide to Synchronous and Asynchronous Code

news2025/1/11 19:44:43

2024/3/12 发布
正在寻觅一份前端开发工作,如果您觉得这篇文章对你有所帮助,这是我的简历1

在这篇文章中你能学习和理解:NodeJS是如何工作、如何处理所有发送给服务器的函数(无论同步或者异步)和请求、Event Loops in NodeJS 。就是在NodeJS环境中同步代码和异步代码是如何执行的,以及event loop是如何管理异步代码的。

背景

想必每位前端开发工程师都能在NodeJS官网-学习入门 处看到这样一句话:NodeJS is an asynchronous event-driven JavaScript runtime environment designed to build scalable network applications.

理解什么是Asynchronous(异步)?

这里的Asynchronous指的是 那些在后台(background)处理不堵塞(blocking)任何其他请求(request)的JS函数(function)

理解什么是Event Loop (事件循环)

在NodeJS 环境中,Node用Event Loop 处理请求。

An event loop是一个内置在NodeJS环境中的事件监听者,它所拥有的一些函数随时准备去监听,处理和为事件进行输出。

用英文解释会更清楚:An event loop is an event-listener which functions inside the NodeJS environment and is always ready to listen, process, and output for an event.

PS:一个事件(an event)可以是鼠标事件,定时事件,键盘事件等。

理解什么是Synchronous programming(同步程序) and Asynchronous programming?

同步程序就是the code运行遵循书写下的序列(sequence),在同步程序中只有一个函数被调用并返回了一个值之后,下一行的函数才能执行。

让我们用以下的代码举个例子:

const listItems = function(items) {
  items.forEach(function(item) {
    console.log(item)
  })
}

const items = ["Buy milk", "Buy coffee"]

listItems(items)

The output will look like this:
“Buy milk”
“Buy coffee”

在这个例子中,当listItems(items)函数被调用后,它会循环抓取items数组元素,console.log(item)函数得到数组第一个元素后输出"Buy milk".然后console.log(item)再次执行时,通过数组第二个元素,输出"Buy coffee"

这就是所谓的函数遵循书写下的序列执行。

换句话来说,异步程序就是代码执行并不遵循明确的序列(sequence)。这些函数并不表现为一个程序中定义的序列,而仅仅当遇见确定的条件。

举个例子,setTimeOut() 表现为在提前指定的毫秒延迟过后执行一个任务。

setTimeOut(function(){
    return( console.log("Hello World!") )
}, 3000) 

这类函数并不是根据书写顺序一行行得运行,仅仅当他们需要被执行,和函数的声明无关,在这个例子中,在所有同步函数(synchronous function)都已经执行完过后,这个输出函数将会在3秒之后自动执行,在同步函数被执行完之前,异步函数会在后台被处理。

理解NodeJS 如何在后台处理异步函数 ,以及如何先执行所有同步函数?所有的这些机制,可以用NodeJS event loop轻松解释。

How Does an Event Loop Work?

用一个diagram来看看NodeJS event loop 如何执行一个简单的同步程序:
在这里插入图片描述
左上角是一个即将被执行的Node file,左下角是一个程序输出端,以及你会拥有 Call stack, Node APIs and Callback queue. 所有这些组成了这个 NodeJS environment.

对于同步程序,只需要关注call stack ,这是这个例子下,NodeJS 环境唯一会产生工作的地方。(call stack 就是一个数据结构,用于在程序中锁定所有函数的执行)

当程序开始执行,首先call stack 注入一个匿名main()函数,这个机制是NodeJS默认的。
在这里插入图片描述
接下来,变量a和b被创建,以及他们的和被存储在变量sum中。所有的取值都被存储在内存中。
现在,console.log()是一个函数,它被调用以及push到call stack ,然后执行,你就会在输出端的屏幕中看到它的输出结果。
在这里插入图片描述
当函数执行完毕,就会从call stack 中被移除。接着,当程序没有剩下的东西被调用,main()也会被移出call stack。以上就是同步程序执行的过程
在这里插入图片描述
在这里插入图片描述

现在,来看在NodeJS中异步程序如何执行。异步程序就需要call stack 、Node APIs、callback queue 全部一起参与处理。
看下面这个例子:
在这里插入图片描述
和上面的一样,当程序开始执行,第一步是main()被添加到call stack中。然后console.log("Start")被调用和添加到stack栈。进过处理,输出就在输出端被看见,接着就会从call stack 中被移除。
在这里插入图片描述
在这里插入图片描述
现在下一句是setTimeOut(...Zero...),函数被调用和添加到call stack。

因为这是一个异步函数,它不会在call stack中被处理,它从call stack 添加到Node APIs ,在Node APIs中:事件被注册,回调函数(callback function)被设置并在后台进行处理。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接下来setTimeOut(...Two..)同样的道理进入Node APIs,接着又一个callback function 被设置为在后台两秒之后处理。当这个时刻到来之前,其他函数都可以被执行。
这叫做非阻塞式行为:直到满足条件轮到他们执行之前,所有的同步函数首先在后台被处理和执行
在这里插入图片描述
接下来,console.log("End")函数被最后调用,并在call stack中处理,输出端可以看到输出结果。现在,所有的同步方法都被处理了,然后main()被移除call stack。

在后台,所有的异步函数被处理以及所有的回调函数被存储在callback queue,首先处理的一个将首先添加到队列中,以便在回调堆栈中执行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Note: Asynchronous functions cannot run inside a callback stack until it gets emptied. That means that after main() is removed from call stack, only then can all asynchronous functions start executing.

现在他们被event loop一个个得推入call stack 并得到执行。
每次被调用时这些回调函数都会用console.log()函数打印value。
在这里插入图片描述
最后,这些都会被在执行过后被移除,现在call stack 再次清空了。
在这里插入图片描述
这就是NodeJS环境下 如何执行同步异步函数,以及event loop 如何管理调用异步函数。

Conclusion

在这篇文章中,你理解了NodeJS的内部工作机制,以及明白了异步程序如何被执行。

现在你应该理解为什么2秒的延迟函数没有阻塞其他的程序执行,你也明白为什么0秒的延迟函数在“End”输出后打印其值。

以上就是全部,我希望你们享受这篇文章的内容并学到一些新东西,分享这篇文章如果你觉得它有用!感谢你们的点赞关注和岗位内推!找到工作我会告诉大家!


  1. 我的简历:点击获取,欢迎随时联系我
    If you want to learn more about NodeJS and asynchronous programming, you can refer to this article ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1524362.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache-Doris基础概念

OLAP数据库Doris 一、Doris架构二、基本概念1. Row & Column2. Partition & Tablet3. 建表示例(1)列的定义(2)分区分桶(3)多列分区(4)PROPERTIES(5)E…

Java 面试题之框架

1. Spring 是什么 Sping 是包含了众多工具方法的 IOC 容器,IOC是控制反转,说的是对象的创建和销毁的权利都交给 Spring 来管理了, 它本身又具备了存储对象和获取对象的能力. 。 容器:字面意思,用来容纳某种物品的装置。 比如 L…

通俗易懂的Python循环讲解

循环用于重复执行一些程序块。从上一讲的选择结构,我们已经看到了如何用缩进来表示程序块的隶属关系。循环也会用到类似的写法。 for循环 for循环需要预先设定好循环的次数(n),然后执行隶属于for的语句n次。 基本构造是 for 元素 in 序列: statemen…

RoketMQ主从搭建

vim /etc/hosts# IP与域名映射,端口看自己的#nameserver 192.168.126.132 rocketmq-nameserver1 192.168.126.133 rocketmq-nameserver2# 注意主从节点不在同一个主机上 #broker 192.168.126.132 rocketmq-master1 192.168.126.133 rocketmq-master2#broker 192.168…

网络通信.

1.物理层:网络通信的基础设施 运快递的公路 2.数据链路层 两个相邻的节点之间如何传输 两个集散点之间的传输 3.网络层 两个点之间的路径规划 物流公司规划快递的路径 4.传输层 两个点之间的通信(不考虑路径规划) 卖家发货 只考虑起点和终点 …

C++ 特殊类及单例模式

文章目录 1. 前言2. 不能被拷贝的类3. 不能被继承的类4. 只能在堆上创建对象的类5. 只能在栈上创建对象的类6. 只能创建一个对象的类(单例模式) 1. 前言 在实际场景中,我们在编写类的过程中总会遇到一些特殊情况,比如设计一个类不…

【Godot4.0】自定义A*寻路拓展类TileMapAStar2D及其使用

概述 Godot提供的AStar2D和AStarGrid2D基本可以解决所有2D的A*寻路问题: 前者提供了基础的A*寻路支持,但是需要手动处理很多内容后者针对基于方形图块的A*寻路,进行了很多自动化的工作,用起来十分简便。但是不使用于六边形、iso…

C++for语句(2)

11.乘方计算 给出一个整数a和一个正整数n&#xff08;-1000000<a<1000000,1<n<100000&#xff09;&#xff0c;求乘方&#xff0c;即乘方的结果。最终结果的绝对值不超过1000000。 输入 一行&#xff0c;包含两个整数a和n&#xff08;-1000000<a<1000000,1…

网站安全监测:守护网络空间的坚实防线

随着互联网技术的飞速发展和广泛应用&#xff0c;网站已成为企业、机构和个人展示形象、提供服务、传递信息的重要平台。然而&#xff0c;与此同时&#xff0c;网站也面临着日益严重的安全威胁。黑客攻击、数据泄露、恶意软件等安全问题频发&#xff0c;给网站运营者带来了巨大…

redis发布订阅与stream类型

发布订阅 redis发布订阅(pub/sub)是一种消息通信模式&#xff1b;发送者(pub)发送消息&#xff0c;订阅者(sub)接收消息。redis客户端可以订阅任意数量的频道。 基础命令&#xff1a; 语法 redis publish命令基本语法如下&#xff1a; redis 127.0.0.1:6379> PUBLISH ch…

若你有才能,最好能遇上识才之人,高俅发迹的故事很好诠释了千里马与伯乐的关系

若你有才能&#xff0c;最好能遇上识才之人&#xff0c;高俅发迹的故事很好诠释了千里马与伯乐的关系 其实&#xff0c;“千里马”和“伯乐”都是中国古代传说里的角色。伯乐是古代一个善于相马&#xff08;识别马的好坏&#xff09;的人&#xff0c;而“千里马”则是指一匹能跑…

解决:由于找不到xinput1_3.dll,无法继续执行代码问题的方法

xinput1_3.dll文件的丢失是一个常见的问题&#xff0c;它会导致一些游戏应用程序无法正常运行或出现错误。为了解决这个问题&#xff0c;我们可以采取多种方法。下面将介绍几种常用的xinput1_3.dll丢失的解决方法&#xff0c;通过采用合适的方法&#xff0c;我们可以轻松解决该…

跳绳计数,YOLOV8POSE

跳绳计数&#xff0c;YOLOV8POSE 通过计算腰部跟最初位置的上下波动&#xff0c;计算跳绳的次数

Redis数据结构对象之字符串对象

字符串对象 字符串对象的编码可以是int、raw或者embstr 如果一个字符串对象保存的是整数值&#xff0c;并且这个整数值可以用long类型来表示&#xff0c;那么字符串对象会将整数值保存在字符串对象结构的ptr属性里面(将void *转换成long)&#xff0c;并且将字符串对象的编码设…

zookeeper快速入门四:在java客户端中操作zookeeper

系列文章&#xff1a; zookeeper快速入门一&#xff1a;zookeeper安装与启动-CSDN博客 zookeeper快速入门二&#xff1a;zookeeper基本概念-CSDN博客 zookeeper快速入门三&#xff1a;zookeeper的基本操作 先启动zookeeper服务端。 在maven引入zookeeper依赖。 <depende…

代码算法训练营day10 | 232.用栈实现队列、225. 用队列实现栈

day10: 232.用栈实现队列225. 用队列实现栈 232.用栈实现队列 题目链接 状态&#xff1a; 文档&#xff1a;programmercarl.com 思路&#xff1a; 用栈实现队列。要先明白两者的区别。 栈&#xff1a;单开门&#xff0c;先进后出&#xff0c;只有一端能进出。 队列&#xff1a;…

【晴问算法】入门篇—贪心算法—区间不相交问题

题目描述 给定n个开区间&#xff0c;从中选择尽可能多的开区间&#xff0c;使得这些开区间两两没有交集。 输入描述 输出描述 输出一个整数&#xff0c;表示最多选择的开区间个数。 样例1输入 4 1 3 2 4 3 5 6 7 输出 3 解释 最多选择(1,3)、(3,5)、(6,7)三个区间&#xff0c;它…

从零到一构建短链接系统(三)

1.根据数据库表&#xff0c;利用在线网站https://jully.top/generator/ 根据数据库Info自动生成代码 2.在entity中创建UserDO Data TableName("t_user") public class UserDO { /** * id */ private Long id; /** * 用户名 */ private String username; /** * 密码…

图解Kafka架构学习笔记(一)

本文参考尚硅谷大数据技术之Kafka。 消息队列 &#xff08;1&#xff09;点对点模式&#xff08;一对一&#xff0c;消费者主动拉取数据&#xff0c;消息收到后消息清除&#xff09; 点对点模型通常是一个基于拉取或者轮询的消息传送模型&#xff0c;这种模型从队列中请求信息…

[嵌入式系统-40]:龙芯1B 开发学习套件 -10-PMON启动过程start.S详解

目录 一、龙芯向量表与启动程序的入口&#xff08;复位向量&#xff09; 1.1 复位向量&#xff1a; 1.2 代码执行流程 1.3 计算机的南桥 VS 北桥 二、PMON代码执行流程 三、Start.S详解 3.1 CPU初始化时所需要的宏定义 &#xff08;1&#xff09;与CPU相关的一些宏定义…