JS—异步、回调、高阶函数

并发与并行

  • 并发是指两个或多个事件链随时间发展交替执行,以致于从更高的层次来看,就像是同时运行(但在任意时刻只处理一个事件)
  • 并发的关键是你有处理多个任务的能力,不必定同时。
  • 并行的关键是你有同时处理多个任务的能力。
  • 并发和并行均可以是不少个线程,就看这些线程能不能同时被(多个)cpu执行,若是能够就说明是并行,而并发是多个线程被(一个)cpu 轮流切换着执行。
  • 区别:是否【同时】

并发与并行

  • 单线程事件循环是并发的一种形式
  • 并发的实现方式:多进程,多线程,事件循环
  • 个人理解是:并发是多个逻辑流交替执行,看起来像是同时运行,其实任意时刻只能处理一个;而并行是真正的同时执行。

同步与异步

  • 同步和异步关注的是消息通讯机制 (synchronous communication/ asynchronous communication)
  • 同步,就是在发出一个调用时,在没有获得结果以前,该调用就不返回。可是一旦调用返回,就获得返回值了。
  • 异步则是相反,调用在发出以后,这个调用就直接返回了,因此没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会马上获得结果。而是在调用发出后,被调用者经过状态、通知来通知调用者,或经过回调函数处理这个调用。

阻塞与非阻塞

  • 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态
  • 阻塞调用是指调用结果返回以前,当前线程会被挂起。调用线程只有在获得结果以后才会返回。
  • 非阻塞调用指在不能马上获得结果以前,该调用不会阻塞当前线程。
  • 个人理解:异步阻塞是没有必要的;ajax请求最好不要设置为同步,chrome浏览器会警告

阻塞与非阻塞,同步与异步知乎连接
阻塞与非阻塞与是否同步异步无关javascript

事件循环

  • 机制:while(true)每轮循环取出事件队列中的队头事件执行,事件队列(先进先出)。
  • setTimeout()是设定一个定时器,当定时器到时后,环境会把回调函数放到事件循环中。若是此时事件队列中有多个事件,那么该回调就会等待,因此setTimeout定时器的精度可能不高,只能确保回调函数不会在指定的时间间隔以前运行。
  • AJAX请求:JS程序发出ajax请求,从服务器端获取数据,并设置了回调函数。发出请求的时候,JS引擎会通知宿主环境,让其完成了网络请求,拿到数据后执行该回调函数。而后,浏览器会设置侦听来自网络的响应,拿到数据后,将该回调函数插入到事件循环。
  • 竞态条件:函数执行顺序的不肯定性(来自于插入事件队列顺序的不肯定性)
  • 竞态条件可能会致使结果的不肯定性,因此须要经过协调交互顺序来解决这种状况。
  • 并发协做:JS中个人理解是:将大任务分解为多个小任务,分别利用异步机制插入到事件队列中,例如可利用setTimeout(f,0)将小任务插入到事件队列中,若是事件队列目前有待执行的事件就能够先执行,以此来避免大任务阻塞事件队列中其余任务的执行。

JavaScript单线程与异步

  • why单线程:做为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操做DOM。这决定了它只能是单线程,不然会带来很复杂的问题。
  • why异步:个人理解:浏览器应用决定了会有不少网络请求,会有不少不可控的速度因素,浏览器是直接和用户交互,用户交互体验很重要,因此不能阻塞,但同步非阻塞处理起来会很麻烦,由于同步须要编写代码去检测任务是否执行成功。因此就用异步,异步是通讯机制决定了调用在发出以后就能够直接返回。
  • 全部同步任务执行完毕,系统就会循环读取事件队列。
  • 阮一峰的连接:http://www.ruanyifeng.com/blo...
  • 深刻理解事件循环
  • 深刻事件循环

回调

  • 回调是JS中最基础的异步模式
  • 回调地狱:1)难以编写,大脑的思惟方式不适应面向回调的异步代码。2)为了处理可能出现的各类状况,只能在回调的每一个步骤中硬编码,形成代码的复杂与重复,难以重用和维护。
  • 信任问题:控制反转,即把本身程序的一部分执行控制交给了某个第三方。

高阶函数

  • JS做为一门完整的面向对象的编程语言,借鉴了函数式语言的特性,好比闭包、高阶函数等。
  • 高阶函数: 函数可做为参数被传递,函数可做为返回值输出。
  • 函数做为参数被传递:

1)回调函数,即将变化部分的代码封装为函数,将函数做为参数传递。原本能够将变化的部分抽离出来,造成两个函数,但实际上这两个函数有依赖关系,因此只能参数调用,放到同一个函数中执行。
2)Array.prototype.sort 能够传入函数做为排序规则。html

异步控制台

  • JS调试最好使用断点,由于console.log()是由宿主环境添加到JS中,控制台I/O处理可能会有延时。

《你不知道的javascript中卷》第二部分异步和性能 1.1 异步控制台部分: java

并无什么规范或一组需求指定console.* 方法族如何工做——它们并非JavaScript 正式
的一部分,而是由宿主环境(请参考本书的“类型和语法”部分)添加到JavaScript 中的。所以,不一样的浏览器和JavaScript 环境能够按照本身的意愿来实现,有时候这会引发混淆。 git

尤为要提出的是,在某些条件下,某些浏览器的console.log(..) 并不会把传入的内容当即输出。出现这种状况的主要缘由是,在许多程序(不仅是JavaScript)中,I/O 是很是低速的阻塞部分。因此,(从页面/UI 的角度来讲)浏览器在后台异步处理控制台I/O 可以提升性能,这时用户甚至可能根本意识不到其发生。github

例如在mousemove监听函数中console.log,是不会打印出内容的(mousemove触发太频繁,而console.log属于I/O操做,浏览器为了性能考虑,会将这种频繁I/O放到后台运行)。 ajax

解决方案: 若是断点调试不方便的话,能够将须要打印的内容,挂载到window对象,mousemove完成后再打印出来看。chrome

更多博客: https://github.com/Lmagic16/blog编程

相关文章
相关标签/搜索