引子
在网页应用程序(以下简称“web应用”)中进行非同步操作,是从 Ajax
重新火起来之后带来的 XMLHttpRequest
开始风靡的,现在,开发者可以运用各种相关的模式来辅助执行非同步操作。当然,web应用中除了部分需要非同步操作(如取数据等),大部分还仍然以同步操作为主。
近来,Node.js 袭来,因为它大规模采用了非同步操作,使得不少开发者留意到同步与非同步操作之间存在的显著差异,也开始重视非同步操作的各种模式。
回调模式
回调就是所谓的 callback,台湾译作“回呼”,当实现程序出现许多重复流程,仅小部分需要特定实现时,那么一般会有的处理情况是:把重复流程的实现作为样板,而特定实现则通过“呼叫者”提供回调对象或函数。
例如:
有Js数组:[1,3,2,5,4],对其进行排序,我们会考虑如下实现:
[1, 3, 2, 5, 4].sort(function(a, b) { return a-b;});
再如:
在浏览器使用非同步对象 XMLHttpRequest
时,由于判断环境、发出请求、回应等流程是可重复利用的,因此可封装,也就是说在进行非同步请求的同时,提供回调函数,以便在浏览器获得“远端”对“非同步请求”的回复时予以处理,可以看jQuery的实现:
$.get(url, options, function(responseText) { ... }); // 第三个就是回调函数
通过上面两个例子,我们可以看出回调模式的特点:
- 封装了大部分流程
- 仅要求呼叫者提供对应事件发生时相对应的回调
- 这种模式对呼叫者友善,逻辑清晰
回调这种非同步操作模式有几点不好的:
- 对开发者来说,如果用同步操作的习惯来对待回调函数的执行结果,将会产生不正确的执行结果
- 如果非同步操作串连在一起的话,则会形成回调地狱(Callback hell)的问题,影响可读性
连续调用
英文名称是:Continuation-passing style,简称CPS,它是一种流程控制风格,如果用回调方式来实现,那么是通过函数将其执行结果传给呼叫者提供的回调函数,因而形成一种连续呼叫的风格。
这个模式目前看的还是比较晕,先放链接吧:非同步操作的多種模式
Promise模式
这种模式在不同语言中有不同的称呼,如 future,delay 或是 deferred 模式。
Promise 对戏那个基本上是作为一个代理对象,代表着一段可能长时间执行或延后执行的计算,并承诺在未来提供计算结果,无论那是成功、失败或其他可能的结果。
对于angular中的promise写法,项目中也是运用很多,比如通过 then()
解决回调地狱的问题,还可以使用 try ... catch
配合 reject
和 resolve
进行代码书写。
写在最后
最后说下这篇文章是想说,其实我们运用非同步操作很多,Js中,包括各种库和框架也都提供了这方面的支持,理解它其实是作非同步(异步)操作的,就是最重要的了。
最后这边有篇文章,希望有时间的可以看看:JavaScript异步编程