JavaScript异步编程的方法
Posted T1amo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript异步编程的方法相关的知识,希望对你有一定的参考价值。
异步编程:
在浏览器端,异步编程非常重要,耗时很长的操作都应该异步执行,避免浏览器失去响应。最常见的例子就是通过AJAX向服务器发送异步请求。
异步编程有很多种方法
1、回调函数
比如有两个函数
f1();
f2();//f2依赖于f1的执行状态
如果f1耗时很长,它会阻塞后面程序的运行
我们利用setTimeout来改写f1,因为setTimeout是异步的
function f1(callback){ setTimeout(function(){ //f1的代码,耗时很长,这里是又开启了一个线程, callback();//f1完后执行callback() },1000) } f1(f2);//这段代码不会阻塞后面的程序运行,f2依赖于f1的执行状态
采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。
这种方法很简单,也容易理解,但是不利于代码的阅读和维护,各个部分之间高度耦合,而且每个任务只能指定一个回调函数
2、事件监听
另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
f1.on(‘done‘,f2);//为f1绑定一个事件(f2订阅事件) function f1(){ setTimeout(function(){ //f1的代码 f1.trigger(‘done‘);//f1触发这个事件(f1发布事件) },1000) }
这种方法可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"有利于实现模块化。
缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
3.发布订阅模式
又称观察者模式,它广泛的应用于异步编程中,是一种代替回调函数的方案。
上面讲到的事件,可以理解成“信号”
假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"一个信号,其他任务可以向信号中心"订阅"这个信号,从而知道什么时候自己可以开始执行。
这就叫做"发布/订阅模式",又称"观察者模式"
发布订阅者模式可以去除对象之间的耦合,有利于实现模块化,而且我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。
这个模式有多种实现,下面采用的是jQuery的一个插件。
//f2向"信号中心"jQuery订阅"done"信号 jQuery.subscribe("done", f2); function f1(){ setTimeout(function () { // f1的任务代码 jQuery.publish("done");//f1执行完成后,向"信号中心"jQuery发布"done"信号,从而引发f2的执行。 }, 1000); }
4.Promise对象
Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口,使得控制异步操作更加的容易
ES6将Promsie纳入了规范,并原生提供了Promise对象
简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:
f1().then(f2);
promise优点在于避免层层嵌套的回调函数,回调函数变成了链式写法,程序的流程可以看得很清楚,并且提供了统一的接口,使得控制异步操作更加的容易。
而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。
这种方法的缺点就是编写和理解,都相对比较难。
例子:我们用promise对象实现AJAX操作
var getJSON=function(url){ var promise=new Promise(function(resolve,reject){ //AJAX操作 $.ajax({ url:url, type:‘GET‘, dataType:‘json‘, success:function(data,status,xhr){ resolve(data); }, error:function(xhr,textStatus){ reject(textStatus); } }) }) return promise; }
getJSON(‘/post.json‘) //任务Resolve状态的回调函数,返回是这个promise对象 .then(function(value) { console.log(value); }) //任务Rejected状态的回调函数 .catch(function(error){ console.log(error); })
采用链式的then方法可以指定按照次序调用的回调函数
如果前一个回调函数返回的是另外一个promise对象,那么后一个回调函数就会等待该promise对象状态发生变化再调用
getJSON("url1") .then(function(value){ return getJSON(value.url2);//返回另外一个promise对象 }) //另外一个promise对象Resolve状态的回调函数 .then(function(value){ console.log(value) })
以上是关于JavaScript异步编程的方法的主要内容,如果未能解决你的问题,请参考以下文章