JavaScript学习笔记-JS中的异步编程
来源:互联网 发布:照片美发软件 编辑:程序博客网 时间:2024/06/14 07:14
刚开始学习JavaScript编程时,你可能就已经知道,JavaScript是单线程(Single Thread)执行的。单线程的意思是一次只能执行一个方法,只有等一个方法返回才会去执行另一个方法。winform编程时如果UI线程中等待的话便会造成UI假死,但是在Web编程中没有线程的概念,也就是说如果代码等待则UI便会卡死。
为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
同步模式便是上述所说的UI卡死的情况;
异步模式的话最普遍的例子就是Ajax方法。
本文总结一些JavaScript中异步编程的方法,如若文中有错误或者有其他异步方法,望不吝赐教。
在下文的示例中会使用setTimeout模拟耗时操作。
1、 回调方法(Callback)
回调是我刚开始接触JavaScript异步时使用的方法,相信也是大多数人的体验。
var x = 0; function f1(callback) { setTimeout(function() { x += 1; callback(); }, 100); } function f2() { alert(x); } f1(f2);
使用回调方法大致就是f1(f2)这样的情况,但是当回调的层级过多的时候代码便会呈现金字塔结构,使代码变得难看并且不易理解和维护,重构的过程也会充满各种陷阱。优点是这种方式会最原始最直接的,目前所有浏览器都能支持,所以也有很多人依然在用这种方式。
2、 事件监听
为了方便演示,下面示例使用JQuery的写法。
var x = 0; f1.on('done', f2); function f1(){ setTimeout(function () { x += 1; f1.trigger('done'); }, 1000); } function f2() { alert(x); } f1();
通过f1.on(‘done’, f2)添加事件监听,当执行f1()方法,trigger触发’done’事件,此时事件被捕捉并响应,执行f2方法。
使用事件监听机制可以避免回调方法的多重嵌套,使代码扁平化。但是使整个程序变成事件驱动模式,使流程更加不清晰(你有时很难看懂执行那个方法后触发事件跳转到另外的方法)。而且会破坏方法的原子性。
3、观察者模式
观察者模式与事件监听机制类似,下面示例同样使用JQuery的写法。
var x = 0; jQuery.subscribe('done', f2); function f1(){ setTimeout(function () { x += 1; jQuery.publish('done'); }, 1000); } function f2() { alert(x); jQuery.unsubscribe("done", f2); } f1();
可以看到,代码上跟事件监听的差异不大,差别只是
f1.on(‘done’, f2)变成了jQuery.subscribe(‘done’, f2),
f1.trigger(‘done’))变成了jQuery.publish(‘done’)。
实际上前者使用的是监听,而后者更类似于通知。与前者相比的话优点是通过信号来统一控制。
4、Promise对象
ES6 原生提供了 Promise 对象。
所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
ES6的Promise来源于Promise/A+。使用Promise来进行异步流程控制,有几个需要注意的问题,
在We have a problem with promises一文中有很好的总结。
Promise 对象有以下两个特点。
(1)对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
var promise = new Promise(function(resolve, reject) { if (/* 异步操作成功 */){ resolve(value); } else { reject(error); }});promise.then(function(value) { // success}, function(value) { // failure});
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 方法和 reject 方法。
如果异步操作成功,则用 resolve 方法将 Promise 对象的状态,从「未完成」变为「成功」(即从 pending 变为 resolved);
如果异步操作失败,则用 reject 方法将 Promise 对象的状态,从「未完成」变为「失败」(即从 pending 变为 rejected)。
更多关于Promise的特性,可以参考:阮一峰ECMAScript 6 入门
5、Generator方法
Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。
function* gen(x){ var y = yield x + 2; return y; }
上面代码就是一个 Generator 函数。它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。
整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用 yield 语句注明。Generator 函数的执行方法如下。
var g = gen(1); g.next() // { value: 3, done: false } g.next() // { value: undefined, done: true }
上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止。
换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。
更多关于Generator的特性,可以参考:Generator 函数的含义与用法
5、async/await
async/await是ES7引进的新特性,即async function和await关键字,目前ES7由于浏览器支持等原因还未能投入生产环境,我们也只能暂时了解一下。
以下是async/await的一个简单示例:
async function testFun() { let res, a, b, c, d; try { res = await f1(a, b); res = await f2(c, res); res = await f3(d); return res; } catch (err) { return handleError(err); }}testFun();
代码跟Promise&Generator实现类似,此处不加以赘述。
以上就是目前JavaScript中实现异步的一些方法,有些直接复制他人的博文,参考的文章也均已给出,里面有更加详细的介绍。
- JavaScript学习笔记-JS中的异步编程
- JavaScript异步编程学习
- js异步编程学习
- 学习JavaScript中的异步Generator
- 学习JavaScript中的异步Generator
- JavaScript异步编程插件–jsDeferred.js
- JavaScript编程中的同步与异步机制
- JavaScript中的异步编程-ES5 & ES6
- JavaScript学习--Item27 异步编程异常解决方案
- Javascript学习笔记_异步模式
- javascript 异步编程javascript
- 《深入浅出Node.js》学习笔记——(四)异步编程
- JavaScript高级编程(学习笔记)
- JavaScript DOM编程 学习笔记
- Javascript模块化编程--学习笔记
- JavaScript中的this学习笔记
- JavaScript学习中的一些笔记
- 深入理解JavaScript编程中的同步与异步机制
- OSG学习笔记17 创建和处理用户定义事件 UserEvent
- HTML(6)表单
- Spring的自动扫描、数据源配置、AOP和事务等配置
- 【调侃】IOC前世今生
- Eclipse的安装及配置
- JavaScript学习笔记-JS中的异步编程
- Open-Drain与Push-Pull
- [Wondgirl]ECMAScript6(ES6)(一)
- 深度学习 3. MatConvNet (CNN)的介绍和下载以及CPU和GPU的安装配置,Matlab2016
- 学解《Effective java》之 构造器到构建器的跨越
- 搭建一个开发Predix软件的Ubuntu 系统(3)配置Java开发环境
- 关于SSD的二三事,NAND闪存的一些常识
- IDEA社区版安装tomcat
- js中return的作用及用法