Home » Code » javascript异步编程的4种基本写法

javascript异步编程的4种基本写法

本文主要参考自阮一峰老师的Javascript异步编程的4种方法

何为“异步”这个水太深,故不在此班门弄斧。知道大概是什么一种什么样的效果就行了,不要在意太多细节~、~

我们假定有两个函数f1、f2,其中f1是一个比较耗时的操作,它要先运行,它完成后才可以执行f2。

function f1(){
	//f1中大量的耗时操作
	setTimeout(function(){
		console.log("this is f1()");
	}, 2000);
}

function f2(){
	console.log("this is f2()");
}

如果只是简单的这么写:

f1();
f2();

这样子肯定是不行的,一来这里用了setTimeout这个特殊函数其实已经是异步的操作,达不到目的(f1没有执行完成f2就执行了)。好吧,怎么看着像是将异步的操作给改成同步的了,这标题。。。好吧,都说了不要在意在这些细节,知道我要干什么就行了。就这个目标,该如何实现呢?

回调函数

这是最基本大家都会的办法,那就是将需要后执行的函数作为先执行函数的回调函数:

function f1(callback){
	//f1中大量的耗时操作
	setTimeout(function(){
		console.log("this is f1()");
		callback();
	}, 2000);
}

function f2(){
	console.log("this is f2()");
}

f1(f2);

事件监听

这是一种事件驱动模式,行为的执行不取决于代码的顺序,而是事件的发生。我们假定f1有一个done事件,为f1的done事件绑定f2,当f1执行完成时触发它的done事件,这样f2就执行了。伪代码如下:

function f1(callback){
	//f1中大量的耗时操作
	setTimeout(function(){
		console.log("this is f1()");
		f1.trigger("done");
	}, 2000);
}

function f2(){
	console.log("this is f2()");
}

f1.on("done", f2);

但上边毕竟是伪代码,f1只是一个普通的函数又不是jQuery对象,怎么能使用on、trigger这些方法呢,更离谱根本没有什么done事件可以供你监听!好吧,这里只是为了说明这一种实现方式的思路。

这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以”去耦合”(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。

发布/订阅

上一节的”事件”,完全可以理解成”信号”。
我们假定,存在一个”信号中心”,某个任务执行完成,就向信号中心”发布”(publish)一个信号,其他任务可以向信号中心”订阅”(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做”发布/订阅模式”(publish-subscribe pattern),又称”观察者模式”(observer pattern)。

原文采用的是Ben Alman的Tiny Pub/Sub举例,其实这个插件就下边几行:

(function($) {

  var o = $({});

  $.subscribe = function() {
    o.on.apply(o, arguments);
  };

  $.unsubscribe = function() {
    o.off.apply(o, arguments);
  };

  $.publish = function() {
    o.trigger.apply(o, arguments);
  };

}(jQuery));

使用它来实现:

function f1(){
	//f1中大量的耗时操作
	setTimeout(function(){
		console.log("this is f1()");
		$.publish("done");//发布"done"信号,订阅的人会执行绑定的函数
	}, 2000);
}

function f2(){
	console.log("this is f2()");
}

$.subscribe("done", f2);//f2向信号中心订阅done信号

f1();

Promise对象

Promise对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:

f1().then(f2)

f1需要进行改写,使它返回一个promise对象,这里是jQuery的实现:

function f1(){
	var dfd = $.Deferred();//获得延迟对象

	//f1中大量的耗时操作
	setTimeout(function(){
		console.log("this is f1()");
		dfd.resolve();//标记已解决
	}, 2000);

	return dfd.promise();//返回promise对象
}

function f2(){
	console.log("this is f2()");
}

f1().then(f2)

这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚。而且可以继续then添加很多回调函数以及通过fail()指定失败时的回调等。jQuery里边的延迟对象Deferred还有很多功能,具体可以了解一下。

上边的这4种方法,其中方法1的回调是最基本最常用的。方法2的事件监听没有具体实现,其实它的原理跟方法3订阅&发布(观察者)基本是一致的。方法4有人说其实只是语法糖,javascript的“异步”只有回调与观察者两种方法。

参考链接:
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.