异步编程有哪几种方法来实现?
1.背景介绍
JavaScript的执行环境是单线程的,单线程的好处是执行环境简单,不用去考虑诸如资源同步,死锁等多线程阻塞式编程等所需要面对的恼人的问题。但带来的坏处是当一个任务执行时间较长时,后面的任务会等待很长时间。在浏览器端就会出现浏览器假死,鼠标无法响应等情况。所以在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应。所谓异步执行,不同于同步执行(程序的执行顺序与任务的排列顺序是一致的、同步的),每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。既然Javascript是单线程的,那它又如何能够异步的执行呢?
2.知识剖析
2.1异步编程有哪几种方法
1.回调函数
2.事件监听
3.Promises对象
4.发布/订阅(观察者模式)
2.2回调函数
这是异步编程最基本的方法。回调函数的优点是简单,轻量级(不需要额外的库)。缺点是各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数,而且,如果再嵌套多几层,代码会变得多么难以理解
这个被称之为“回调函数噩梦”(callback hell)!!!
function fn1(f){ alert(1); f(); };
function fn2(f){ alert(2); f(); };
function fn3(){ alert(3); };
fn1(function(){ fn2(fn3); });
注意 区分 回调函数和异步 回调并不一定就是异步。他们自己并没有直接关系。 简单区分 同步回调 和 异步回调
2.3
事件监听
$("#clickity").on("click", function (e) { console.log("xxxxx");
采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
2.4
Promises对象
Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。 简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:
f1().then(f2); 这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。 比如,指定多个回调函数: f1().then(f2).then(f3);
再比如,指定发生错误时的回调函数:f1().then(f2).fail(f3); 而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。
3.常见问题
何时使用异步?
4.解决方案
在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。在服务器端,"异步模式"甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有http请求,服务器性能会急剧下降,很快就会失去响应。
5.编码实战
6.扩展思考
异步的好处:
1、异步流程可以立即给调用方返回初步的结果。
2、异步流程可以延迟给调用方最终的结果数据,在此期间可以做更多额外的工作,例如结果记录等等。
3、异步流程在执行的过程中,可以释放占用的线程等资源,避免阻塞,等到结果产生再重新获取线程处理。
4、异步流程可以等多次调用的结果出来后,再统一返回一次结果集合,提高响应效率。
7.参考文献
https://www.jb51.net/article/78757.htm
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
8.更多讨论
1,问:何时使用异步
答:耗时较长的任务,影响后面任务执行,造成浏览器失去响应,都可以使用异步,
2,问:回调函数一定是异步吗
答:不一定,回调函数有同步回调和异步回调,
3,问:promise是什么
答:Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。 简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数,具体知识可以去网上详细了解一下promise。