理解javascript的同步与异步模式

2023-11-15

你可能知道,Javascript语言的执行环境是"单线程"(single thread)。

所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。

这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。

为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。

"同步模式"就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;"异步模式"则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

"异步模式"非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。在服务器端,"异步模式"甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有http请求,服务器性能会急剧下降,很快就会失去响应。


异步调用并不会阻止代码的顺序执行,而是在将来的某一个时刻触发设置好的逻辑,所以我们
  1. 并不知道逻辑什么时候会被调用
  2. 只能定义当触发的时候逻辑是什么
  3. 只能等待,同时可以去处理其他的逻辑

setTimeout就是这样的一个异步调用。

var a = 1;     
function f1(a){
	console.log("I am in f1");
	setTimeout(function () {
	  a += 2;
	  console.log("f1:"+a);	  
	}, 1000);
}
f1(a);
console.log("out:"+a);
得到的结果如下所示:

I am in f1
out:1
f1:3

可以看出来代码的执行过程确实是先执行了f1函数,再进行console输出,但是setTimeout的回调函数却在执行过程中被挂起,直到1s过后才被调用。在等待过程中javascript选择先执行后面的操作,即console输出。

实际上,异步函数,如setTimeout和setInterval,是被压入了称之为Event Loop的队列。

Event Loop是一个回调函数队列。当异步函数执行时,回调函数会被压入这个队列。JavaScript引擎直到异步函数执行完成后,才会开始处理事件循环。这意味着JavaScript代码不是多线程的,即使表现的行为相似。事件循环是一个先进先出(FIFO)队列,这说明回调是按照它们被加入队列的顺序执行的。JavaScript被 node选做为开发语言,就是因为写这样的代码多么简单啊。

Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。(这也被称之为非阻塞式IO或者事件驱动IO)在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。


在Node.js 异步编程的直接体现就是回调,下一篇将注重讲解回调函数的使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解javascript的同步与异步模式 的相关文章

  • 如何从一维数组和静态字符串创建对象

    我想要一个像 var obj ABC name true dob true CDE name true dob true EFG name true dob true CBA name true dob true XYZ name true
  • 使用 JavaScript 格式化日期

    JavaScript 中的日期格式有问题 这是我的函数代码 originalDate 2016 03 02 09 12 14 989522 var d new Date originalDate month d getMonth 1 day
  • 循环遍历数组并删除项目,而不中断 for 循环

    我有以下 for 循环 当我使用splice 要删除一个项目 我发现 秒 未定义 我可以检查它是否未定义 但我觉得可能有一种更优雅的方法来做到这一点 我们的愿望是简单地删除一个项目并继续 for i 0 len Auction auctio
  • javascript:全局变量泄漏

    每当我向 Firefox 提交插件时 我都会收到一封电子邮件 告诉我我的一些变量正在泄漏到全局范围内 一旦他们告诉我我解决了问题 但在那之前有什么方法 程序 来检查变量是否泄漏到全局范围内 Thanks Both JSLint http w
  • 通过纯 JavaScript 获取 div 的第 n 个子元素

    我有一个名为 myDiv 的 div 元素 我怎样才能得到 myDiv 的第n个孩子DOM https en wikipedia org wiki Document Object Model操纵 Markup function reveal
  • Chrome 扩展程序可以相互通信吗?

    我正在编写一个Chrome扩展程序 并且想要实现一个接口或api 以便我将来制作的其他扩展程序可以使用它 最终的效果可能如下 分机 B 呼叫extensionA someMethod someParameters 并向分机A发送一些数据 分
  • 如何在 google.maps.event.addListener 中使用它

    以下示例有效 但是当我尝试传递参数并使用this在该功能不起作用 Working google maps event addListener markers i click showInfoWindow function showInfoW
  • Visual Studio 改变 Ctrl-K-D 的工作方式

    In Visual Studio I m using 2012 is there any way of editing the way that Ctrl K D combinations handles its Auto Formatti
  • 如何在 JavaScript 中将变量的内容写入文件[重复]

    这个问题在这里已经有答案了 可能的重复 firefox 如何启用本地 JavaScript 来读取 写入我的 PC 上的文件 https stackoverflow com questions 2846045 firefox how to
  • 转义 \u200b(零宽度空格)和其他非法 JavaScript 字符

    我有一组 JavaScript 对象 我引导到后端模板 以在页面加载时初始化我的 Backbone js 集合 它看起来像这样 作为 Twig 模板 我遇到的问题是某些文本字段包含 u200b 零宽度空格 这会破坏
  • 如何调试超时等待异步 Angular 任务?无法在角度页面上找到元素

    编辑 请注意 在 ernst zwingli 的帮助下 我找到了问题的根源 因此 如果您遇到相同的错误 他指出的修复之一可能会帮助您 我的问题是量角器本身的一个已知问题 如果您认为这可能是您 我已经扩展了我的步骤 以在我最初的问题之后查明问
  • 冒泡可用于图像加载事件吗?

    我可以用吗 window addEventListner 某种程度上来说 我所有的图像都有一个display none 图像加载后 我想设置display inline 这样我就可以规范下载图像时显示的内容 在这种情况下 我无法预加载图像
  • Riak 在 MapReduce 查询中失败。使用哪种配置?

    我正在与 riak riak js 结合开发一个 nodejs 应用程序 并遇到以下问题 运行此请求 db mapreduce add logs run 正确返回存储在存储桶日志中的所有 155 000 个项目及其 ID logs 1GXt
  • Aurelia 中的角度服务?

    我还没有找到详细说明如何从 Angular 1 x 迁移到 Aurelia 的详细文档 到目前为止 我只看到人们详细介绍了 Angular 的概念directive可以在 Aurelia 中使用重制 customElement 好吧 足够简
  • 嵌套 DIV 的类似斑马的 CSS 样式

    我嵌套了 DIV 元素 但我不知道嵌套的级别 我需要每个都有与其父级不同的背景 创建类似斑马的颜色 我只使用两种背景 深色和白色 效果需要类似于在容器中设置奇数和偶数子级的样式 但在我的例子中 子级是嵌套的 我可以使用每个嵌套元素的规则来做
  • 如何使用 GreaseMonkey 让浏览器恢复“/”键?

    Lots of web pages seem to use the key for searching I d like to disable that because 100 of the time I want to use to se
  • AngularStrap 工具提示禁用我的自定义指令

    我正在尝试让 bs tooltip AngularStrap 指令与我自己的名为 checkStrength 的自定义指令一起使用 该指令检查密码的强度 单独使用这些指令中的任何一个时 它们都可以正常工作 但不能一起工作 This http
  • 在 Nodejs 中,如何停止 FOR 循环直到 MongoDB 调用返回

    我正在研究下面的代码片段 我有一个名为 stuObjList 的 JSON 对象数组 我想循环遍历数组以查找具有特定标志集的特定 JSON 对象 然后进行数据库调用以检索更多数据 当然 FOR 循环不会等待数据库调用返回并到达 j leng
  • 使用 File API polyfill 读取数据 URL

    我正在尝试使用文件 API 库 https github com mailru FileAPI https github com mailru FileAPI 作为不支持文件 API 的浏览器的后备 以便将文件作为数据 URL 读取并将其传
  • $ 在 JQuery 中意味着什么

    在下面的 var obj one 1 two 2 three 3 four 4 five 5 each obj function i val console log val 这里是什么意思 是对象吗 是一个别名jQuery对象 函数 它充当

随机推荐

  • The file “xxx” couldn’t be opened because you don’t have permission to view it. You don’t have permi

    问题 Xcode 使用真机编译不报错 运行报如下错误 The file xxx couldn t be opened because you don t have permission to view it You don t have p
  • Py之pdpbox:深度解析Python数据探索库PDPbox

    Py之pdpbox 深度解析Python数据探索库PDPbox PDPbox是一个基于Python的数据探索工具库 可以帮助用户更好地理解数据特征之间的关系以及其对模型性能的影响 该库提供了多种数据可视化和解释工具 方便用户进行快速实验和分
  • python wheel文件

    wheel介绍 whl文件 WHL file 也称为轮子 wheel 这是用于python分发 distribution 的标准内置包格式 standard built package format 它包含安装所需的所有文件和元数据 met
  • 实证研究的步骤_案例研究法

    案例研究法是实地研究的一种 研究者选择一个或几个场景为对象 系统地收集数据和资料 进行深入地研究 用以探讨某一现象在实际生活环境下的状况 比如民族志研究 扎根理论等 可观察也可仅通过资料分析进行研究 适用条件 当现象与实际环境边界不清而且不
  • 使用httpwebrequest发送数据到网站

    怎样通过HttpWebRequest 发送 POST 请求到一个网页服务器 例如编写个程序实现自动用户登录 自动提交表单数据到网站等 假如某个页面有个如下的表单 Form
  • vue简单实现div滚动触底加载更多数据效果

    vue简单实现div滚动触底加载更多数据效果 1 html div class webTherapyAuditList div里放置一些需要滚动加载的信息 滚动函数通过 scroll触发 div 2 js 获取页面滚动距离 handleSc
  • js 获取tabel Cell 内input 的信息

    1 要建立一个清单 在网页表格内输入信息并可以获取保存 这里只写如何获取table 里单元格里input 或 textarea 的信息 2 html 的代码如下 table tr td r name td td r value1 td td
  • arcgis---填充面要素空洞

    1启动编辑 选中面要素 2构造要素选面 3绘制一个包含空洞的任意多边形 4按住shift 选择合并 属性可选择1 2 5 加载绘图工具 使用矩形工具绘制任意的图形覆盖所有图形 6将图形要素转换成面要素 7分析工具 标识 8数据管理 多部分至
  • ROS Navigation-----map_server简介

    map server包提供了一个map server ROS Node 该node通过ROS Service方式提供地图数据 该包还提供了map saver命令行utility 使用该工具可将动态创建的地图保存成文件 1 Map forma
  • 日常——js

    1 闭包 1 1 概念 闭包指 有权访问另一个函数作用域中变量的函数 1 2 优缺点 优点 闭包函数中的变量不会随着闭包函数销毁而销毁 而是要等到还在使用它的函数销毁时才会销毁 缺点 频繁使用闭包会造成内存泄漏 闭包 会将它的外部函数的作用
  • 如何获取 两个日期之间的 天数

    获取两个日期对应的时间戳 1 然后时间戳的差 24 60 60
  • 最大子序列和及序列起始位置-全负数也适用-O(N)时间复杂度

    有一个很经典的题目 给定一个整数组 求连续子序列的最大和 整数为正 负 0皆有可能 先考整数不是全负的情况 和最大的连续子序列 必然是以一个非负数开头 因为和加上一个负数 和变小 此外 和为负数的连续子序列 也不可能是目标子序列的开头的一段
  • 申请苹果个人开发者账号流程

    因为经常有人问我怎么申请苹果开发者账号 这里记录下来方便使用 准备 1 一个苹果账号 Apple ID 2 一张开通visa或master功能的信用卡 3 身份证正反面照片 4 一部苹果手机 5 一个手机号 申请流程 一 先注册一个苹果账号
  • python报错:ImportError: cannot import name ‘calinski_harabaz_score‘ from ‘sklearn.metrics‘解决方案

    报错 ImportError cannot import name calinski harabaz score from sklearn metrics 解决方案 harabaz 改为harabasz 成功解决
  • idea强制回退gitlab分支代码

    1 如果合并分支出错 执行以下两步操作 1 切换到本地分支 找到要回退到的点 2 找到本地该项目的文件目录 空白处右键选择 git bash here 将本地分支代码强推到远程库 执行命令符 git push f origin develo
  • 1.MySQL数据库的基本操作

    数据库操作过程 1 用户在客户端输入 SQL 2 客户端会把 SQL 通过网络发送给服务器 3 服务器执行这个 SQL 把结果返回给客户端 4 客户端收到结果 显示到界面上 数据库的操作 这里的数据库不是代表一个软件 而是代表一个数据集合
  • Navicat 15安装教程,强烈推荐收藏!

    Navicat是一款轻量级的用于MySQL连接和管理的工具 非常好用 使用起来方便 简洁 下面讲讲其安装的过程 1 进入navicat官网 选择Navicat for MySQL 然后点击进行下载即可 官网连接 http www navic
  • VSCode+Qt+MinGW开发环境搭建

    VSCode Qt MinGW开发环境搭建 概述 VSCode扩展性很强 插件机制让其具备不断演进的潜力 适合作为稳定的开发工具 VSCode Qt开发环境的搭建需要依赖于以下工具 VSCode Qt 其中Qt需要安装MinGW编译工具 V
  • 【python-数据分析】笔记1

    数据库vs 仓库 数据库 gt 业务存储 针对应用 仓库 gt 主题存储 针对分析 数据来源 Kaggle 阿里云天池 在python console输入 import pandas as pd df pd read csv data HR
  • 理解javascript的同步与异步模式

    你可能知道 Javascript语言的执行环境是 单线程 single thread 所谓 单线程 就是指一次只能完成一件任务 如果有多个任务 就必须排队 前面一个任务完成 再执行后面一个任务 以此类推 这种模式的好处是实现起来比较简单 执