请指出我学习异步Javascript过程中的错误

2023-12-06

我是 Javascript 和异步编程的新手,有些事情让我感到困惑,请指出我学习中的错误。

  • 异步函数的回调被放入消息队列中 通过事件循环执行。
  • 异步执行是非阻塞的,完成 通过事件循环。
  • 功能类似于setTimeout是异步的。
  • 异步函数是阻塞的,只有它们的回调是阻塞的 非阻塞。

以上如有错误,请指出。


异步函数的回调被放入消息队列中并通过事件循环执行。

No.

一般来说两种异步函数 - 一种在完成时需要某种回调来运行,另一种则生成 Promise 作为结果。

基于回调的函数

这是基于回调的函数的示例:

setTimeout(() => console.log("foo"), 0);

console.log("bar");

/* output: 
bar
foo
*/

setTimeout将延迟稍后执行的回调。即使超时为零毫秒,它仍然会安排回调,直到after当前执行已完成,因此顺序为:

  1. setTimeout安排回调。
  2. console.log("bar") runs.
  3. 回调与console.log("foo") runs.

没有一个message队列,有一个队列tasks执行。作为一个简短的概述,事件循环从队列中获取一个任务并执行它直至完成,然后获取下一个任务并执行它直至完成,等等。一个简单的伪代码表示是:

while(true) {
    if (eventQueue.hasNext()) {
        task = eventQueue.takeNext();
        task();
    }
}

有关事件循环的更多信息,请参阅此处。

话虽如此,事件循环的影响更大setTimeout比许多其他基于回调的函数。基于回调的函数的其他示例是 jQuery 的$.ajax()或者 Node.jsfs用于文件系统访问的模块(其非承诺 API)。他们和其他人也接受稍后执行的回调,但边界因素不是事件循环,而是函数执行的任何底层操作。如果是$.ajax() when回调的调用取决于网络速度、延迟和响应请求的服务器。所以,虽然回调will由事件循环执行,其他一切也是如此。所以,这没什么特别的。仅有的setTimeout这里有一个更特殊的交互,因为根据可用的任务,计时可能不精确 - 如果您安排某些任务在 10 毫秒内运行,而某些任务需要 12 毫秒才能完成,则回调计划为setTimeout不会准时运行。

基于 Promise 的函数

这是一个例子:

async function fn(print) {
  await "magic for now";
  console.log(print);
}

fn("foo")
  .then(() => console.log("bar"));

/* output: 
foo
bar
*/

(为了便于说明,我现在省略了很多细节。)

从技术上讲,Promise 是针对处理异步操作而定制的回调的抽象。这.then()Promise 的方法接受回调并执行它after承诺得到解决,这也会在异步操作完成后发生。因此,我们可以按照正确的顺序一起执行:

async function fn(print) {
  await "magic for now";
  console.log(print);
}

fn("foo");
console.log("bar");

/* output: 
bar
foo
*/

在某种程度上,Promise 是一种回调,因为它们是用来替代 Promise 并以大致相同的方式执行的。您仍然可以传递回调以在成功或失败时执行。但他们不是just回调.

无论如何,给予 Promise 的回调是still延迟:

Promise.resolve()
  .then(() => console.log("foo"));
  
console.log("bar");


/* output: 
bar
foo
*/

但不通过与事件队列相同的事件队列setTimeout用途。有两个队列:

  • 宏任务队列 -setTimeout把东西放在里面,所有的UI交互也都添加到这里。
  • 微任务队列 - 承诺在这里安排他们的事情。

当事件循环运行时,微任务队列(即promise)具有最高优先级,然后是宏任务队列。这导致:

setTimeout(() => console.log("foo")); //3 - macrotask queue

Promise.resolve()
  .then(() => console.log("bar")); //2 - microtask queue
  
console.log("baz"); //1 - current execution


/* output: 
baz
bar
foo
*/

无论如何,我认为我不太愿意说基于 Promise 的函数通过回调来工作。有点是的,但是是在还原论的意义上。

异步执行是非阻塞的,通过事件循环完成。

No.

什么是“阻塞”?

首先,让我们明确一点——阻塞行为是指环境正忙于执行某些操作时的行为。通常在该执行期间不能运行其他代码。因此,进一步的代码是blocked从跑步。

我们以这段代码为例:

setTimeout(taskForLater, 5000);

while (somethingIsNotFinished()) {
    tryToFinish();
}

Here taskForLater将被安排在 5 秒内运行。但是,那while循环将block执行。由于没有其他代码将运行,taskForLater可能会在 10 秒内运行,如果这是循环完成所需的时间。

运行异步函数并不总是意味着它会运行在平行下使用当前代码。在大多数情况下,环境一次执行一件事。 JavaScript 默认情况下没有多线程,并行执行是一种选择行为,例如通过使用workers.

什么是“异步执行”?

这可能意味着几件事,但不清楚您引用的是哪一个:

  1. 运行异步函数的主体
  2. 等待底层异步操作完成

在这两种情况下,引用的陈述都是错误的,但原因不同。

异步函数的主体

异步函数是承诺的语法糖。它们使用相同的机制,但只是以不同的方式呈现代码。然而,异步函数正在阻塞。附带说明一下,Promise 执行器(给予 Promise 构造函数的回调)也是如此。在这两种情况下,该函数都会运行并阻止直到有什么事情导致它暂停。演示它的最简单方法是使用异步函数 - 使用await will暂停该函数的执行并安排其余部分稍后完成。

全身都堵住了:

async function fn() {
  console.log("foo");
  
  console.log("bar");
}


fn();
console.log("baz");

/* output:
foo
bar
baz
*/

中间停顿一下:

async function fn() {
  console.log("foo");
  await "you can await any value";
  console.log("bar");
}


fn();
console.log("baz");

/* output:
foo
baz
bar
*/

作为澄清一点,any价值是可以等待的,而不仅仅是承诺。等待非承诺仍然会暂停并恢复执行,但由于没有什么可等待的,这将导致它成为微任务队列上的首要任务之一。

无论如何,执行异步函数的主体might堵塞。要看具体是什么操作。

底层异步操作

当谈论“底层操作”时,大多数时候我们的意思是将控制权交给其他东西,例如浏览器或库。在这种情况下,当前的 JavaScript 环境不会完成该操作,我们称之为将执行操作并仅在操作完成时通知当前 JavaScript 环境的东西。例如,在浏览器中调用fetch将触发网络请求,但处理它的是浏览器,而不是我们的代码。所以它是非阻塞的,但不是在执行环境之外。

fetch("https://official-joke-api.appspot.com/random_joke")
  .then(res => res.json())
  .then(joke => console.log(joke.setup + "\n" + joke.punchline));

console.log("foo");

话虽如此,我们甚至无法概括给定的异步操作将做什么。它实际上可能会阻塞执行,至少会阻塞一段时间,或者可能完全在当前 JavaScript 环境的单独进程中执行。

功能类似于setTimeout是异步的。

Yes.

虽然,它可能正在考虑什么是like setTimeout. Is it setInterval?它是基于回调的异步函数吗?问题在于定义开始变成循环“基于异步回调的函数,例如setTimeout是异步的”。

并非每个接受回调的函数都是异步的。那些are可能被认为类似于setTimeout.

异步函数是阻塞的,只有它们的回调是非阻塞的。

No.

如上所述,异步函数might堵塞。取决于他们具体做什么。例如$.ajax会使用浏览器发起网络请求,类似于fetch。如果是$.ajax该函数在准备请求时会阻塞,但在发送请求后不会阻塞。

该语句的第二个问题是调用非阻塞回调是不正确的 -执行他们肯定会再次阻止执行。回调是一个普通的 JavaScript 代码,当时间到来时将通过事件循环执行。当任务运行完成时,执行仍然被阻止。

如果您的意思是它们是非阻塞的,因为回调将被放入事件队列中,但这仍然不能保证。考虑以下说明性代码:

function myAsyncFunction(callback) {
    const asyncResult = someAsynchronousNonBlockingOperation();
    
    doStuff(result);
    callback(result);
    doMoreStuff(result);
}

Once someAsynchronousNonBlockingOperation()产生一个值执行callback不会安排在稍后,但将成为处理该结果的同步代码序列的一部分。所以,callback将被处决later但它本身并不是一项任务,而是一项总体任务的一部分,其中包括doStuff and doMoreStuff.

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

请指出我学习异步Javascript过程中的错误 的相关文章

  • 计算div中有多少个元素

    我有一个div 里面有span 有没有一种方法可以计算 div 中有多少个元素 然后将其作为值给出 例如 一个 div 中有 5 个跨度 那么它会对其进行计数并发出警报 5 请使用 JavaScript 谢谢 如果你想要后代的数量 你可以使
  • 如何使用文档客户端更新 dynamodb 中的嵌套列表数据

    我有一个 dynamoDB 表 其中有一个包含 UserId 和列表列表的项目 它看起来像这样 Item UserId abc123 Lists id 1 title My favorite movies topMovies id 1 ti
  • 优化重叠矩形的绘制

    我有很多矩形 有些与其他矩形重叠 每个矩形都有一个绝对 z 顺序和一个colour 每个 矩形 实际上是粒子效果 网格或纹理的轴对齐边界框 并且可能是半透明的 但只要您不尝试剔除其他矩形后面的矩形 就更容易抽象地思考彩色矩形 所以我将在问题
  • 如何使用 RSpec 测试 javascript 重定向?

    我正在使用 xhr post 与控制器交互 并且我期待重定向 在 js erb 中 我有 window location href address 手动测试 浏览器会正确重定向 我如何使用 RSpec 测试它 response should
  • 通过 Amazon SQS 将压缩文本从 PHP 发送到 NodeJS

    我似乎一直坚持通过 Amazon SQS 将压缩消息从 PHP 发送到 NodeJS 在 PHP 方面我有 SQS gt sendMessage Array QueueUrl gt queueUrl MessageBody gt artic
  • 检测 JavaScript 版本

    如何检测浏览器支持的 JavaScript 版本 如果有 我想检查 ECMAScript 3 ECMAScript 5 和 ECMAScript 6 注意 我想避免已弃用的language tag 这里有一个很好的参考给你 http www
  • 如何使用谷歌地图检测一个点是否在多边形内部?

    我想检测到google maps LatLng是在一个里面google maps Polygon 我怎样才能做到这一点 Cheers 你可以使用这个谷歌地图V3 google maps geometry poly containsLocat
  • 如何从矩形点计算旋转角度?

    我有4分1 2 3 4闭合一个矩形 这些点按以下方式排列在数组中 x1 y1 x2 y2 x3 y3 x4 y4 我遇到的问题是矩形可以旋转一定角度 如何计算原始点 灰色轮廓 和角度 我试图在 javascript css3 transfo
  • 如何为多个元素添加Class?

    我正在使用这段 javascript 向多个元素添加一个类 我试图引用多个 div 并向它们添加类 它只适用于第一个 JavaScript
  • React-Router v5 History.push 不触发组件

    很抱歉朋友们又问这个问题了 我找到了解决这个问题的几个方法 但他们让我很困惑 我只是想问一个优雅的方法来做到这一点 正如你通过标题所理解的 我有一个关于反应路由的问题 让我解释 我有一个按钮 其名称是Login 单击按钮后 我执行了一些逻辑
  • 在javascript中通过window.location传递数据

    我试图通过 window location 传递数据 数据在 del id img album 中可用 我想通过 window location 发送多个值 window location save php type deldownload
  • 如何设置第三方 cookie

    我如何设置第三方 cookie 我有要求设置cookie 并且cookie将在访问的网站中启用 就像我在访问cde com或def com或ghi com时在abc com中设置cookie一样 所以设置的cookie将在所有网站上获取 我
  • Ajax调用完成后执行函数

    我是 Ajax 新手 我尝试在使用 for 循环时使用 Ajax Ajax 调用之后 我正在运行一个使用 Ajax 调用中创建的变量的函数 该函数只执行两次 我认为 Ajax 调用可能没有足够的时间在循环开始之前进行调用 有没有办法在运行
  • 添加元数据到快速路线

    有什么方法可以将元数据添加到 Express 的路线中吗 例如 app get some route function req res some meta data 我正在寻找一种针对我的节点应用程序的 AOP 方法 因此我想通过身份验证和
  • 为什么react中的组件需要大写? [复制]

    这个问题在这里已经有答案了 因此 当您声明一个组件以小写首字母进行反应时 它不会显示 也不会引发错误 当您将组件名称大写时 它确实有效 这样的实现是怎样的呢 为了避免与现有的 html 元素发生冲突 还是这是一个错误 var test Re
  • 以特定顺序运行具有效果的 jQuery 函数

    我在 javascript 函数中有一些 jQuery 可以更改页面上的文本并以特定的时间间隔淡入和淡出 我希望这些函数在每个函数完成其效果后按顺序运行 dialogueExchange1 dialogueExchange2 dialogu
  • 检测未定义的对象属性

    如何检查 JavaScript 中的对象属性是否未定义 检查属性值是否为特殊值的常用方法undefined is if o myProperty undefined alert myProperty value is the special
  • 来自 ajax 的 Bootstrap 表 json

    我有 ajax 和 bootstrap 表的问题 我有一个 ajax JSON 我用这个方法调用 document ready function ajax url php process php method fetchdata dataT
  • 带有 'as' 属性的通用 React TypeScript 组件(能够渲染任何有效的 dom 节点)

    我在下面的示例中按预期工作 我的问题是 无论如何我可以重写它 这样我就不必传递通用的T和as支柱 理想情况下我想通过asprop 并让组件的 prop 接口使用它 这在 TypeScript 中可能吗 export type Props l
  • 使用 document.getElementsByName() 不起作用?

    第二个警报命令的代码按预期工作 显示元素 to 的值 但第一个警报命令不起作用 它应该做同样的事情 这是为什么

随机推荐

  • wxpython菜单栏不显示

    我正在尝试使用 wxpython for gui 编写一个时间表程序 并使用 wxpython wiki 上的入门教程来加快 wxpython 的速度 但是当我尝试向 wxFrame 添加菜单栏时 菜单栏不显示 有什么想法为什么会发生这种情
  • 如何在 Intel 环形和网状架构上选择引导处理器 (BSP)

    第2 13 2节提到仲裁 ID 用于确定哪个处理器首先发出无操作周期 我在多个来源和英特尔手册上看到了这一点 引用 MP 初始化序列的英特尔手册仅在存在 系统总线 时以及在此之前最初存在 APIC 总线 时解决 Pentium 4 我的印象
  • 在 iOS (Flutter) 中使用 Firebase 和 Geolocator(或任何 Swift 插件)构建错误

    我正在尝试创建一个使用 Firebase 和 Geolocator 插件的 flutter 应用程序 我将使用的 Firebase 插件认证 使用RTDB and FCM The 地理定位器显然是一个非常可靠的位置感知插件 在 Androi
  • 如何在 Windows 上通过内置命令使用 subprocess.Popen

    在我的旧 python 脚本中 我使用以下代码来显示 Windows cmd 命令的结果 print os popen dir c read 正如 python 2 7 文档所说os popen已经过时并且subprocess被推荐 我按照
  • 实例成员“view”不能在类型“GameScene”上使用

    我最近更新到 Xcode 7 Beta 现在收到一条错误消息 实例成员 视图 无法在第 5 行的 GameScene 类型上使用 有人知道如何解决此问题吗 另外 如果您想提供额外帮助 请参阅我的另一个问题 ConvertPointToVie
  • 在智能卡上上传 .cap 文件?

    我有一张新卡 其 ATR 代码如下 3B 68 00 00 00 73 C8 40 12 00 90 00 我在谷歌上搜索了这张ATR 最后我知道这是一张 巴西电子公积金卡 问题是我该如何使用这张卡 我的意思是它支持哪些 APDU 有它的数
  • PHP - 使用表单输入中的 id 制作 switch 语句

    我正在用 PHP 做一个简短的测验 根据 4 个是 否问题告诉你你想到的生物是什么 我这样做是为了根据您对每个问题的回答 您会遇到不同的问题 我主要使用 switch 语句来完成此操作 我的问题是有什么方法可以使用条件作为表单提交按钮的 i
  • Flutter 蓝牙热敏打印机集成

    我有一个 flutter 食品配送应用程序 除此之外 我还有一个单独的餐厅应用程序 我可以在其中接受和拒绝订单 我很长一段时间以来一直在尝试做一些事情 以便当餐厅接受订单时 蓝牙热敏打印机会自动打印出一张收据 我找到了很多代码 但我不明白如
  • Powershell:将 pracl 命令的输出通过管道传输到数组

    pracl 是一个 sysinternal 命令 可用于列出目录的 ACL 我有一个共享列表 我想创建一个 csv 文件 这样对于每个 ACL 条目 我希望共享路径位于一列中 共享权限位于下一列中 我试图通过使用以下代码来做到这一点 inp
  • 数组到 SVG,使用 PHP 的灵活算法

    问题 我有几个不同的数组 例如 0 21 0 001 0 0245 0 31 0 05 1234 1342 1232 1625 2200 2205 1804 5 12 42 2 32 42 my problem now is I m loo
  • 在 Python 中索引浮点值

    我有一个从数据结构生成的浮点数列表 它是一个字典列表 即我已经迭代了整个列表并选择了给定字典中的某些值 现在 我想实际对这些数据点做一些事情 为此我需要对原始位置的一些参考 我尝试简单地使用数据点作为关键 但在尝试和失败之后 我进行了一些挖
  • Google VR Unity Divider、设置和后退按钮隐藏在 v0.9 中

    有谁知道如何禁用最新的 google vr sdk for unity 中的分隔符 设置和后退按钮 我尝试将 NativeUILayerSupported 设置为 false 并将返回值放入旧的 DrawUILayer 中 但它仍然显示 看
  • Web Api - 使用 [FromBody] 属性和 POST 方法时操作参数为空

    我有这个控制器 但我不明白为什么name参数为空 public class DeviceController ApiController HttpPost public void Select FromBody string name pr
  • 全透明OpenGL模型

    解释一下我做错了什么 我已将 3D 模型加载到自编码的 opengl 渲染 v 3 3 中 并尝试使用顶点着色器使其像 xray 效果一样透明 version 330 attribute vec3 coord3d attribute vec
  • Python 通过请求更改 Instagram 个人资料图片

    我正在尝试使用 python post 请求更改我的 Instagram 个人资料图片 但它没有改变 我没有收到任何错误 在回复中 它说他们已经更改了它 但是更改为白色 Instagram 人物照片 而不是我选择的照片 request ur
  • 为什么不能从 ArrayAdapter 添加/删除项目?

    我正在使用一个ArrayAdapter
  • SQL Server 长查询中的表锁 - 解决方案:NoLock?

    我的应用程序中的报告运行一个需要 5 15 秒的查询 仅限于将返回的行数 该查询对我的应用程序的几乎所有主表 客户 销售 单位等 有 8 个联接 一个小工具向我展示 此时 所有这 8 个表都被共享表锁锁定 也就是说 此时不会进行任何更新操作
  • targetSdkVersion 26 在崩溃报告中给出异常

    根据到 2018 年 11 月将目标 SDK 版本更新到 26 的要求 我在几个月前尝试更新我的 gradle 文件并发布了我的应用程序的新版本 将目标 sdk 和编译 sdk 版本更新为 26 从 23 之后 一天之内 我开始在 Fire
  • 未找到 Gradle DSL 方法:“classpath()”

    项目 FeedBack 可能使用不包含该方法的 Android Gradle 插件版本 例如 在 1 1 0 中添加了 testCompile 修复插件版本并同步项目 项目 FeedBack 可能使用不包含该方法的 Gradle 版本 打开
  • 请指出我学习异步Javascript过程中的错误

    我是 Javascript 和异步编程的新手 有些事情让我感到困惑 请指出我学习中的错误 异步函数的回调被放入消息队列中 通过事件循环执行 异步执行是非阻塞的 完成 通过事件循环 功能类似于setTimeout是异步的 异步函数是阻塞的 只