javascript异步编程

回调函数和事件监听在实现异步编程的时候有什么不同?事件监听不也需要回调函数吗?还有所谓的AJAX操作,作为一个异步任务,其到底是借助回调函数还是事件监听来完成异步的了?越想越觉得晕,希望大牛可以指点,谢谢了....

阅读 3.2k
3 个回答

说下个人理解,希望可以帮到你:

1.回调函数与异步编程没有必然联系

当我们说回调函数时,我们是指把一个函数当作参数传递给 API 提供者,让 API 在恰当的时机调用这个函数。这是一种 API 设计方式,我们为了接口灵活设计了函数类型的参数,方便数据进出。但回调函数并不一定涉及到异步的问题,传入的函数也可能被同步执行。

2.事件监听是一种设计模式

JS中的事件其实是发布-订阅者模式的实现,其实也就是一种 API 设计方式。事件监听可以使用回调函数的方式实现,你可以说它使用了回调函数,但确切说是把函数作为订阅器当参数传递给产生事件的对象。DOM 中你也可以把实现了特定接口但对象作为订阅起传递给 EventTarget

var eventHandler = {
    handleEvent: function(e) {
        console.log(e)
    }
};
document.body.addEventListener('click', eventHandler)

事件监听是一种设计模式,它可以用来实现异步编程的API设计。

3. 类似浏览器的 AJAX 是如何实现异步的

Ajax 接口设计使用了事件模式,而 JS 中事件监听通常都是由传递函数作为参数来完成,在事件模式下这个函数不叫回调函数,叫事件监听器。无论我们在讨论回调函数还是事件监听,我们讨论的都是接口设计的问题,我们不能说异步任务是借助接口设计来实现的,我们只能说某种接口设计方法适用于异步任务

如果你真想弄明白 JS 中的异步任务,你就要跳出前端的范畴,去了解浏览器,去了解操作系统,甚至硬件。

4. 当我们在说同步还是异步,我们具体指什么

这个问题看似简单,但是要深得这些概念的要领并不简单。我们说同步接口调用,是指当我调用某个接口的时候,我什么也不干,就在这里等着,调用的接口什么时候完成,我什么时候接着往下执行别的任务。异步接口调用,是指我发出调用的指令后,继续忙别的去,异步任务完成再通知我。

我曾经也思考过,异步方式有什么优势么?更高效吗?从单核 CPU 角度讲,CPU 一个时刻只能做一件事,即使我们使用异步方式调用任务接着去做别的事,也并不会提高总的效率啊,甚至反而影响了我们调用的这个任务的完成时间。其实不然。计算机在处理 I/O 任务的时候,比如磁盘、网卡和内存进行数据交换时,并不占用 CPU 资源。CPU这个时候完全可以继续执行其他任务。I/O 任务完成后,硬件层面会发起 I/O 中断给 CPU,CPU 这时候加载中断程序处理 I/O 的结果。个人理解,这才是异步任务实现的本质。

所以我们说的同步/异步,最终落脚都是在 I/O 任务上,无论磁盘、网络请求,定时器也好,他们从硬件层面就和 CPU 是使用中断方式异步交互的。你如果仔细想就会发现,JS中的一个任务或者说一个函数之所以是异步的,追根溯源,往往是因为最终调用了某个 Native 的函数,比如 setTimeout,比如 Ajax 请求。因为这些函数是异步的,所以我们上层的任务也需要设计成异步的。setTimeout 能工作不是因为有一段代码在不停地 check 时间到没到,是因为计算机硬件里有定时器编程模块,所以操作系统就能实现这种 API,所以浏览器或者说 JS 引擎才能提供 setTimeout 给 JS 用。

早期操作系统在设计多任务的时候,对待 I/O 是按照同步方式进行的,一个任务如果需要调用 I/O ,操作系统会向指定硬件发送调用指令,同时把这个任务挂起转而执行其他任务,直到硬件发送中断,操作系统再把挂起的任务重新恢复。这样的结果就是,从开发者角度看 I/O 任务就像普通的 CPU 计算任务一样,是同步返回结果的。但是如果开发者希望程序同时还能响应用户操作,还可以进行别的计算那怎么办?于是操作系统就给开发者引入线程

线程也有它的弊端,为了保持问题的简单性,浏览器并没有引入线程概念给 JS 开发者。浏览器底层是否使用线程这个毋需讨论,从 JS 角度看浏览器中执行的代码是单任务型,同一时刻不会有两个代码片段在执行,所以一切的 I/O 任务就必须设计成异步调用方式,JS 中函数的便捷恰恰让异步调用变得简单和轻量。

所以说,异步任务本质是借助硬件和CPU之间的交互是异步而实现的。

以上。

回调和事件监听是异步编程的两种常用模式。只是一种固定写法,两种写法可以很方便的互相转化。其实同步编程也能使用,但是优势不大而已。

回调,常用于一个单个监听,临时监听。
事件监听,常用于多个监听,持久监听。

ajax 底层是多线程实现的。

新手上路,请多包涵
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题