异步

关于异步和并发小总结

  • 所谓同步,就是在发出一个"调用"时,在没有得到结果之前,该“调用”就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由“调用者”主动等待这个“调用”的结果。而异步则是相反,"调用"在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在"调用"发出后,"被调用者"通过状态、通知来通知调用者,或通过回调函数处理这个调用。异步模式,即与同步模式相反,可以一起执行多个任务,函数调用后不会立即返回执行的结果,如果任务A需要等待,可先执行任务B,等到任务A结果返回后再继续回调。
  • 实际上,JavaScript 程序总是至少分为两个块:第一块现在运行;下一块将来运行,以响 应某个事件。尽管程序是一块一块执行的,但是所有这些块共享对程序作用域和状态的访 问,所以对状态的修改都是在之前累积的修改之上进行的。
    一旦有事件需要运行,事件循环就会运行,直到队列清空。事件循环的每一轮称为一个 tick。用户交互、IO 和定时器会向事件队列中加入事件。
  • 任意时刻,一次只能从队列中处理一个事件。执行事件的时候,可能直接或间接地引发一 个或多个后续事件。
    并发是指两个或多个事件链随时间发展交替执行,以至于从更高的层次来看,就像是同时在运行(尽管在任意时刻只处理一个事件)。
    通常需要对这些并发执行的“进程”(有别于操作系统中的进程概念)进行某种形式的交互协调,比如需要确保执行顺序或者需要防止竞态出现。这些“进程”也可以通过把自身分割为更小的块,以便其他“进程”插入进来。

关于回调函数-------其实简单理解的话就是在一个函数执行完毕后,得到想要的特定数据后在去执行的函数。回调函数通常是作为参数的函数,对于回调函数的参数有两种方式传参,一个是同等级,一个是内部函数定义。回调函数是一段可执行的代码段,它以「参数」的形式传递给其他代码,在其合适的时间执行这段(回调函数)的代码。

  • 回调函数它是事件循环“回头调用”到程序中的目标,队列处理到这个项目的时候会运行它。settimeout?
  • 在函数内部,语句 以可预测的顺序执行(在编译器以上的层级!),但是在函数顺序这一层级,事件(也就 是异步函数调用)的运行顺序可以有多种可能。
  • 回调函数是 JavaScript 异步的基本单元。但是随着 JavaScript 越来越成熟,对于异步编程领域的发展,回调已经不够用了。
  • 第一,大脑对于事情的计划方式是线性的、阻塞的、单线程的语义,但是回调表达异步流 程的方式是非线性的、非顺序的,这使得正确推导这样的代码难度很大。难于理解的代码 是坏代码,会导致坏 bug。
    我们需要一种更同步、更顺序、更阻塞的的方式来表达异步,就像我们的大脑一样。
  • 第二,也是更重要的一点,回调会受到控制反转的影响,因为回调暗中把控制权交给第三 方(通常是不受你控制的第三方工具!)来调用你代码中的 continuation。这种控制转移导 致一系列麻烦的信任问题,比如回调被调用的次数是否会超出预期。
    可以发明一些特定逻辑来解决这些信任问题,但是其难度高于应有的水平,可能会产生更 笨重、更难维护的代码,并且缺少足够的保护,其中的损害要直到你受到 bug 的影响才会 被发现。

我们需要一个通用的方案来解决这些信任问题。不管我们创建多少回调,这一方案都应可 以复用,且没有重复代码的开销。
我们需要比回调更好的机制。到目前为止,回调提供了很好的服务,但是未来的 JavaScript 需要更高级、功能更强大的异步模式。本书接下来的几章会深入探讨这些新型技术。

并行和并发

  • 并行的形式:多进程、多线程、单线程事件循环、io多路复用
  • 区别:并发是多个‘进程’逻辑流交替执行,看起来像是并发,其实任意时刻只处理一个。而并行是真正的同时执行。

异步和同步

  • 关注的是消息通信机制
  • 同步:在一个调用发出之后,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到结果值了。
  • 异步:调用在发出之后这个调用就返回了,所以没有返回结果。即当一个异步调用发出去之后,调用者不会立刻得到结果,而是在调用者发出之后,被调用者通过状态,通知来通知调用者,或者通过回调函数来处理这个调用。
  • 异步任务会在当前脚本的所有同步任务执行完才会执行

阻塞和非阻塞

  • 关注的是程序在等待调用结果(消息、返回值)时的状态。
  • 阻塞:调用结果返回之前,当前线程会被挂起。调用线程只有得到返回结果之后才会返回。
  • 非阻塞:不能立刻得到结果之前,该调用不会阻塞当前线程。

事件循环

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

JavaScript单线程与异步

  • why单线程:作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的问题。
  • why异步:我的理解:浏览器应用决定了会有很多网络请求,会有很多不可控的速度因素,浏览器是直接和用户交互,用户交互体验很重要,所以不能阻塞,但同步非阻塞处理起来会很麻烦,因为同步需要编写代码去检测任务是否执行成功。所以就用异步,异步是通信机制决定了调用在发出之后就可以直接返回。
    所有同步任务执行完毕,系统就会循环读取事件队列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值