js中的同步异步

“同步”  “异步” 这个词平时见到的很频繁,感受一直出如今平时的生活中,可是没怎么用过,写代码的时候也不多往这上面去考虑。前端

第一次看到 “同步” “异步” 是寒假写小程序的时候, 有一个方法当时特地用的同步(小程序不少方法都分为同步和异步两种 可能由于比较敏感把)。编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  onCollectionTap: function (event) {
 
    var postsCollected = wx.getStorageSync('posts_collected');
    var postCollected = postsCollected[this.data.currentPostId];
    postCollected = !postCollected;
    //取反操做 让收藏变成未收藏 为收藏变成收藏
    postsCollected[this.data.currentPostId] = postCollected;
    //更新文章 是否 的缓存值
 
    // wx.showToast({
    //   title: postCollected?'收藏成功':"取消成功",
    //   duration: 900,
    //   icon:"success"
    this.showToast(postsCollected, postCollected);
  },

 

 这个是从本地获取缓存数据,看这篇文章是否被我收藏了(由于没有后台记录 是动态的绑定数据 因此要这样作去避免刷新以后以前的收藏就没了)  那么我去获取那个我用来标记是否以前收藏过的变量时,就得是一个同步的方法。  那么这个时候就要思考  同步和异步是什么, 何时应该用哪种。小程序

就这个问题 我当时问过一个学长,他当时给我解释的意思,大概就是看 这件事情 重不重要 对于我进程影响大不大 去考虑用同步好 仍是异步好  。 举个看的不少的例子。  关于点单这个问题浏览器

平时买奶茶,可能先去点个单,跟人家说 我要一杯观音铁奶,好,而后这个时候你想去旁边的文具店逛一逛文具,看看有啥书想看的想买的。由于我已经买单了,我能够先去作别的事情了 那么我不须要坐在那里等待,由于我不必一直等着人家作好 而后拿着奶茶去逛文具店,这对我不是那么重要,我彻底能够先作别的事情 过会回来拿。因此这就是异步了,我已经买单,那么我不打算等待,老板作奶茶这件事情我不是很关心,因此我能够同时作一些别的事情,彷佛这个时候两件事情是一块儿作的。(后面会提出个人一点疑问) 那接着我在文具店了,诶,这个时候我我想买一本柯南,可是书架上最新的柯南卖完了,我不知道我是否看过最新本的,我必须等着老板帮我找库存,而后拿出来,我再肯定我是否要买(这是假设我必定要等着这件事情,我很关心 很看重,跟买奶茶不同)那么这个过程就是同步的。缓存

 

 

Javascript语言是一门单线程的语言网络

 单线程和异步确实不能同时成为一个语言的特性。js选择了成为单线程的语言,因此它自己不多是异步的,多线程

可是你想啊,浏览器只分配给js一个主线程,用来执行那些函数,一次只能执行一个,这些任务造成一个任务队列排队等候执行,但前端的某些任务是很是耗时的(我以前也说过,有的时候 前端没写好,,实际上是能够当黑客的 把人家电脑卡死),好比网络请求,定时器(定时器必定要记得清啊! 我以前写像素鸟的时候  那个管子不停的生成 虽然会清理 可是我把页面就放那里 无论它 可能 过一会 它就本身积累了一堆的管子在那里  特别吓人 )和事件监听,若是让他们和别的任务同样,都老老实实的排队等待执行的话,执行效率会很是的低,甚至致使页面的假死。因此,浏览器为这些耗时任务开辟了另外的线程,主要包括http请求线程,浏览器定时触发器,浏览器事件触发线程,这些任务是异步的。下图说明了浏览器的主要线程。那js的宿主环境(浏览器)就很显而易见的能够看出来是多线程了把,因而 为了解决js的这些严重问题  ,宿主环境经过某种方式(事件驱动,下文会讲)使得js具有了异步的属性 ,异步


这就是js的神奇地方  我的以为计算机有意思就是由于有不少神奇的机智的地方async

单线程就意味着,全部任务须要排队,前一个任务结束,才会执行后一个任务。若是前一个任务耗时很长,后一个任务就不得不一直等着。因而就有一个概念——任务队列。若是排队是由于计算量大,CPU忙不过来,倒也算了,可是不少时候CPU是闲着的,由于IO设备(输入输出设备)很慢(好比Ajax操做从网络读取数据),不得不等着结果出来,再往下执行。因而JavaScript语言的设计者意识到,这时主线程彻底能够无论IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回告终果,再回过头,把挂起的任务继续执行下去。异步编程

因而,全部任务能够分红两种,一种是同步任务(synchronous),另外一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。

具体来讲,异步运行机制以下:

(1)全部同步任务都在主线程上执行,造成一个执行栈(execution context stack)。
(2)主线程以外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的全部同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,因而结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。

 

这个时候我看到第二,三条我就在想 按它文字逻辑,就成了我把那些函数放在任务队列,等我有空了再去执行那个函数,若是我一开始就决定最后作那件事情 就变得跟同步没啥区别了

开始各类查资料 先贴一些别人博客的描述

 

异步和多线程有什么区别?其实,异步是目的,而多线程是实现这个目的的方法。异步是说,A发起一个操做后(通常都是比较耗时的操做,若是不耗时的操做就没有必要异步了),能够继续自顾自的处理它本身的事儿,不用干等着这个耗时操做返回。.Net中的这种异步编程模型,就简化了多线程编程,咱们甚至都不用去关心Thread类,就能够作一个异步操做出来。

 

异步操做的本质

  全部的程序最终都会由计算机硬件来执行,因此为了更好的理解异步操做的本质,咱们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友确定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候能够不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始本身和内存交换数据,在传输完成以后硬件会触发一个中断来通知操做完成。这些无须消耗CPU时间的I/O操做正是异步操做的硬件基础。因此即便在DOS 这样的单进程(并且无线程概念)系统中也一样能够发起异步的DMA操做。

 

异步调用并非要减小线程的开销, 它的主要目的是让调用方法的主线程不须要同步等待在这个函数调用上, 从而可让主线程继续执行它下面的代码.与此同时, 系统会经过从ThreadPool中取一个线程来执行,帮助咱们将咱们要写/读的数据发送到网卡.因为不须要咱们等待, 咱们等于同时作了两件事情. 这个效果跟本身另外启动一个线程来执行等待方式的写操做是同样的.可是, 异步线程能够利用操做系统/.Net的线程池, 系统能够根据吞吐量动态的管理线程池的大小.

=======================================================================
异步与多线程,从辩证关系上来看,异步和多线程并不时一个同等关系,异步是目的,多线程只是咱们实现异步的一个手段.什么是异步:异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回.实现异步能够采用多线程技术或则交给另外的进程来处理

 

 

看了这么多以后 我彷佛有点懂了 ,再返回去看 前面提到的  IO设备(输入输出设备) 和 CPU    哇就以为本身好蠢...  差点就想为了这件事情去问斌哥  还好还好 我选择了本身思考 

再来捋一遍,为何会卡呢  由于 IO太慢了啊  而IO跟cpu没有冲突啊...  我彻底可让它慢慢输入输出  而后我本身先去执行别的  好比我先去逛逛文具店  因此 其实两件事情确实是同时在发生的,可是并无占着一个线程,因此不叫多线程,本质上依旧是单线程   再看一眼那一大段引用的关于异步操做的本质的文字   拥有DMA功能的硬件在和内存进行数据交换的时候能够不消耗CPU资源  因此一点都不冲突。 【我对计算机的这些东西有一些盲点,,因此也不知道理解的是否正确 】

 

 

 以上是针对于一些数据读取异步过程的一个处理  可是像定时器,感受好像 应该不是这样 因而去查了一下  还有一个东西叫  Web Worker

Web Worker 的做用,就是为 JavaScript 创造多线程环境,容许主线程建立 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,二者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(一般负责 UI 交互)就会很流畅,不会被阻塞或拖慢。

Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(好比用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通讯。可是,这也形成了 Worker 比较耗费资源,不该该过分使用,并且一旦使用完毕,就应该关闭。

Web Worker 有如下几个使用注意点。

(1)同源限制

分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

(2)DOM 限制

Worker 线程所在的全局对象,与主线程不同,没法读取主线程所在网页的 DOM 对象,也没法使用documentwindowparent这些对象。可是,Worker 线程能够navigator对象和location对象。

(3)通讯联系

Worker 线程和主线程不在同一个上下文环境,它们不能直接通讯,必须经过消息完成。

(4)脚本限制

Worker 线程不能执行alert()方法和confirm()方法,但可使用 XMLHttpRequest 对象发出 AJAX 请求。

(5)文件限制

Worker 线程没法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

 

 

 

 

 

 

 

最后一个环节,再来看几个关于异步的一些题目(更新中...  demo还没彻底弄好)

 

 

 

 

 

-------~~~  (  回调函数使用很少,因此等之后详细用过以后再来写博客  )   ~~~-------

 

 

-------~~~   to be continued ~~~-------

相关文章
相关标签/搜索