Javascript实现异步编程的过程

相信不少人对Javascript单线程表示怀疑:为何单线程可以实现异步操作呢?其实Javascript确实是单线程的(我们不妨把这个线程称作主线程),但它实现异步操作的方式确实借助了浏览器的其他线程的帮助。那其他线程是怎么帮助Javascript主线程来实现异步的呢?答案就是任务队列(task queue)和事件循环(event loop)。

任务队列

首先,作为单线程语言,在Javascript中定义的任务都会在主线程中执行。但是并不是每个任务都会立刻执行,而这种不立刻执行的任务我们称作异步任务。相反,那些立刻执行的任务我们把它们称作同步任务。而这些异步任务都会交给浏览器的其他线程去执行,但是主线程需要了解这些异步任务执行的状态,才方便进行下一步操作。

打个比方,主线程准备做饭,所以下达一个异步任务去买菜,异步任务买完菜之后得告诉主线程:“我买完菜啦”,这个时候主线程才好开始做饭。

而我们知道因为Javascript是单线程,所以上述的“下一步操作”没法直接定义在主函数里(不然就被当做同步任务直接执行了),那这些应该定义在哪里呢?答案就是异步任务的回调函数中。在Javascript异步机制中,任务队列就是用来维护异步任务回调函数的队列。这样一个队列用来存放这些回调函数,它们会等到主线程执行完所有的同步函数之后按照先进先出的方式挨个执行。那么执行完任务队列之后呢?Javascript主线程就执行完毕了吗?当然不是,不然网页加载完毕之后,谁来处理后续与用户的交互事件(比如点击事件)呢?

事件循环

我们通过上图来更加形象的了解Javascript的异步机制。

执行同步任务 -> 检查任务队列中是否有任务 -> [有如果则执行] -> 检查任务队列中是否有任务 -> [有如果则执行] -> ......
可见主线程在执行完同步任务之后,会无限循环地去检查任务队列中是否有新的“任务”,如果有则执行。而这些任务包括我们在异步任务中定义的回调函数,也包括用户交互事件的回调函数。通过事件循环,Javascript不仅很好的处理了异步任务,也很好的完成了与用户交互事件的处理。因为在完成异步任务的回调函数之后,任务队列中的任务都是由事件所产生的,因此我们也把上述的循环过程叫做事件循环。

异步机制实践

console.log('定时器去买菜吧')
setTimeout(function(){
 console.log('菜买完了,主线程去做菜吧')
}, 0)
console.log('你先去买菜,我先看个世界杯')

在浏览器中执行上述代码,兴许能更好地理解Javascript的异步机制。

总结

总而言之,Javascript单线程的背后有浏览器的其他线程为其完成异步服务,这些异步任务为了和主线程通信,通过将回调函数推入到任务队列等待执行。主线程所做的就是执行完同步任务后,通过事件循环,不断地检查并执行任务队列中回调函数。

(0)

相关推荐

  • 异步JavaScript编程中的Promise使用方法

    异步? 我在很多地方都看到过异步(Asynchronous)这个词,但在我还不是很理解这个概念的时候,却发现自己常常会被当做"已经很清楚"(* ̄? ̄). 如果你也有类似的情况,没关系,搜索一下这个词,就可以得到大致的说明.在这里,我会对JavaScript的异步做一点额外解释. 看一下这段代码: var start = new Date(); setTimeout(function(){ var end = new Date(); console.log("Time elap

  • 新手如何快速理解js异步编程

    前言 异步编程从早期的 callback.事件发布\订阅模式到 ES6 的 Promise.Generator 在到 ES2017 中 async,看似风格迥异,但是还是有一条暗线将它们串联在一起的,就是希望将异步编程的代码表达尽量地贴合自然语言的线性思维. 以这条暗线将上述几种解决方案连在一起,就可以更好地理解异步编程的原理.魅力. ├── 事件发布\订阅模式 <= Callback ├── Promise <= 事件发布\订阅模式 ├── Async.Await <= Promise

  • nodejs异步编程基础之回调函数用法分析

    本文实例讲述了nodejs异步编程基础之回调函数用法.分享给大家供大家参考,具体如下: Node.js 异步编程的直接体现就是回调. 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了. 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数. 例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回.这样在执行代码时就没有阻塞或等待文件 I/O 操作.这就大大提高了 Node.js 的性能,可

  • 深入理解JS异步编程-Promise

    前言 "JS 是基于单线程事件循环"的概念构建的,回调函数不会立即执行,由事件轮询去检测事件是否执行完毕,当执行完有结果后,将结果放入回调函数的参数中,然后将回调函数添加到事件队列中等待被执行. 同时也讲了回调函数的问题: 一是"回调地狱",因为异步回调函数的特点:回调函数是作为异步函数的参数,一层一层嵌套,当嵌套过多,将使代码逻辑变得混乱,也无法做好错误捕捉和处理(只能在回调函数内部 try catch). 二是回调的执行方式不符合自然语言的线性思维方式,不容易被

  • 跟我学习javascript解决异步编程异常方案

    一.JavaScript异步编程的两个核心难点 异步I/O.事件驱动使得单线程的JavaScript得以在不阻塞UI的情况下执行网络.文件访问功能,且使之在后端实现了较高的性能.然而异步风格也引来了一些麻烦,其中比较核心的问题是: 1.函数嵌套过深 JavaScript的异步调用基于回调函数,当多个异步事务多级依赖时,回调函数会形成多级的嵌套,代码变成 金字塔型结构.这不仅使得代码变难看难懂,更使得调试.重构的过程充满风险. 2.异常处理 回调嵌套不仅仅是使代码变得杂乱,也使得错误处理更复杂.这

  • javascript异步编程的六种方式总结

    异步编程 众所周知 JavaScript 是单线程工作,也就是只有一个脚本执行完成后才能执行下一个脚本,两个脚本不能同时执行,如果某个脚本耗时很长,后面的脚本都必须排队等着,会拖延整个程序的执行.那么如何让程序像人类一样可以多线程工作呢?以下为几种异步编程方式的总结,希望与君共勉. 回调函数 事件监听 发布订阅模式 Promise Generator (ES6) async (ES7) 异步编程传统的解决方案:回调函数和事件监听 初始示例:假设有两个函数, f1 和 f2,f1 是一个需要一定时

  • 深入理解JavaScript编程中的同步与异步机制

    JavaScript的优势之一是其如何处理异步代码.异步代码会被放入一个事件队列,等到所有其他代码执行后才进行,而不会阻塞线程.然而,对于初学者来说,书写异步代码可能会比较困难.而在这篇文章里,我将会消除你可能会有的任何困惑. 理解异步代码 JavaScript最基础的异步函数是setTimeout和setInterval.setTimeout会在一定时间后执行给定的函数.它接受一个回调函数作为第一参数和一个毫秒时间作为第二参数.以下是用法举例: console.log( "a" );

  • 详解JavaScript异步编程中jQuery的promise对象的作用

    Promise, 中文可以理解为愿望,代表单个操作完成的最终结果.一个Promise拥有三种状态:分别是unfulfilled(未满足的).fulfilled(满足的).failed(失败的),fulfilled状态和failed状态都可以被监听.一个愿望可以从未满足状态变为满足或者失败状态,一旦一个愿望处于满足或者失败状态,其状态将不可再变化.这种"不可改变"的特性对于一个Promise来说非常的重要,它可以避免Promise的状态监听器修改一个Promise的状态导致别的监听器的行

  • Javascript实现异步编程的过程

    相信不少人对Javascript单线程表示怀疑:为何单线程可以实现异步操作呢?其实Javascript确实是单线程的(我们不妨把这个线程称作主线程),但它实现异步操作的方式确实借助了浏览器的其他线程的帮助.那其他线程是怎么帮助Javascript主线程来实现异步的呢?答案就是任务队列(task queue)和事件循环(event loop). 任务队列 首先,作为单线程语言,在Javascript中定义的任务都会在主线程中执行.但是并不是每个任务都会立刻执行,而这种不立刻执行的任务我们称作异步任

  • 基于javascript的异步编程实例详解

    本文实例讲述了基于javascript的异步编程.分享给大家供大家参考,具体如下: 异步函数这个术语有点名不副实,调用一个函数后,程序只在该函数返回后才能继续.JavaScript程序员如果称一个函数为异步的,其意思就是这个函数会导致将来再运行另一个函数,后者取自于事件队列.如果后面这个函数是作为参数传递给前者的,则称其为回调函数. callback 回调函数是异步编程最基本的方式. 采用这种方式,我们把同步操作变成了异步操作,主函数不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟

  • Javascript中的异步编程规范Promises/A详细介绍

    Javascript里异步编程逐渐被大家接受,先前大家一般通过回调嵌套,setTimeout.setInterval等方式实现,代码看起来非常不直观,不看整个代码逻辑很难快速理解.Javascript里异步函数大概有I/O函数(Ajax.postMessage.img load.script load等).计时函数(setTimeout.setInterval)等. 这些我们都很熟悉,在复杂的应用中往往会嵌套多层,甚至以为某些步骤未完成而导致程序异常,最简单的例子:比如你往DOM中注入节点,你必

  • 单线程JavaScript实现异步过程详解

    前两天硬着头皮在部门内部做了一次技术分享,主题如题.索性整理成文章留个纪念! 要了解异步实现,首先我们得先了解: 同步 & 异步 同步:会逐行执行代码,会对后续代码造成阻塞,直至代码接收到预期的结果之后,才会继续向下执行任务. 异步:调用之后先不管结果,继续向下执行任务. 网上各种文章对同步和异步的解释也不外如是,但是看文字总是有点晦涩难懂!我就生活化的来比拟一下这两个概念吧! 就好比请人吃饭: 比如你要请两个人吃饭,一个是巴菲特,由于他是举世瞩目股神想请他吃饭的人从这里排到了法国,你为表诚意,

  • 详解JavaScript 异步编程

    异步的概念 异步(Asynchronous, async)是与同步(Synchronous, sync)相对的概念. 在我们学习的传统单线程编程中,程序的运行是同步的(同步不意味着所有步骤同时运行,而是指步骤在一个控制流序列中按顺序执行).而异步的概念则是不保证同步的概念,也就是说,一个异步过程的执行将不再与原有的序列有顺序关系. 简单来理解就是:同步按你的代码顺序执行,异步不按照代码顺序执行,异步的执行效果更高: 以上是关于异步的概念的解释,接下来我们通俗地解释一下异步:异步就是从主线程发射一

  • 再谈JavaScript异步编程

    随着前端的发展,异步这个词真是越来越常见了.假设我们现在有这么一个异步任务: 向服务器发起数次请求,每次请求的结果作为下次请求的参数. 来看看我们都有哪些处理方法: Callbacks 最先想到也是最常用的便是回调函数了,我们来进行简单的封装: let makeAjaxCall = (url, cb) => { // do some ajax // callback with result } makeAjaxCall('http://url1', (result) => { result =

  • javascript异步编程代码书写规范Promise学习笔记

    最近工作轻松了点,想起了以前总是看到的一个单词promise,于是耐心下来学习了一下. 一:Promise是什么?为什么会有这个东西? 首先说明,Promise是为了解决javascript异步编程时候代码书写的方式产生的. 随着javascript的发展,异步的场景越来越多.前端有AJAX,setTimeout等,后端Node异步更多.按照传统的做法,那么就是各种回调嵌回调.代码可以把人绕晕. 这个时候,CommonJS社区提出了一个叫做Promise/A+的规范,这个规范定义了如何书写异步代

  • JavaScript中实现异步编程模式的4种方法

    你可能知道,Javascript语言的执行环境是"单线程"(single thread). 所谓"单线程",就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推. 这种模式的好处是实现起来比较简单,执行环境相对单纯:坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行.常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他

随机推荐