在上文中我们我们依次说到了一些关于前端异步编程的实现方案:回调函数、事件监听、promise、async/await 等,其实上面说到的这些异步实现方案已经够我们平时开发使用了。接下来我们介绍一下关于前端异步处理的更高层面的实现:响应式编程。上文中我们提到关于promise可以简单总结为:它是在尚未完成且即将在未来某一时间点完成的异步操作。那么响应式编程的提出又解决了一些什么样问题呢?接下来我一起学习一下关于前端的响应式编程。
1、响应式编程理解
响应式编程:面向数据流和变化传播的编程范式。对于这个官方说法可能有点难以理解,下面来说说我自己的理解吧。先提取两个重要概念:数据流、变化传播
数据流:它是一个一组有序,有起点和终点的字节的数据序列。在前端我们可以把变量、用户操作、缓存、数据结构等符合这个条件的,都可以把它理解成数据流。
变化传播:数据流我们可以把它当成一个实际的执行过程,那么我们想要观察这个过程或者对这个过程做一些自定义的操作,然后做出相应的响应便可以理解为变化传播
2、响应式编程构成
响应式编程其实并不是什么新的思想,它其实就是结合了其他的一些优秀思想,然后形成的一个新的编程范式。在理解了一些设计模式及构想后,我们再掉过头去看一些框架的源码实现也就相对较为好理解。下面我们看看他涉及哪些设计思想。
2.1、观察者模式
在上文中我们说过了关于观察者模式的设计思想。它存在一个消息中心,我们可以把它看做是一个收集异步事件流的管理中心,我们可以通过它来观察流、并对事件流做一些自定义操作。从而对流的流向及变化过程达到监听的效果。
2.2、迭代器模式
这个设计模式可能对我们来说都不陌生,就好比我们日常开法中每个迭代一样,它提供一种顺序访问一个聚合对象的每一个元素,又不会暴露该对象的内部结构的统一接口。因此该模式的核心在于实现一个统一遍历的接口。在前端的使用中,该迭代器分为内部迭代器和外部迭代器。
2.2.1、内部迭代器 :一般我们常见的如:for...of、jq中的$each、v-for 、ng-for等,它拥有一次调用,控制整个迭代过程特点。
2.2.2、外部迭代器:在es6 可通过generator来实现一个外部迭代器。
由上图可以看出外部迭代器需要手动控制下一个迭代项,因此外部迭代器能够更灵活的应对复杂的迭代需求。
在响应式编程中,每一个事件流都能通过在订阅消息时,都可以通过迭代器模式来对事件流做自定义的处理,而不用关心每一层处理具体的实现方式。
2.3、函数式编程
在上面我们说了可通过观察者来监听事件流的动态,通过迭代器自定义事件流的处理。那么我们应该怎样去处理关于流的一些相关信息呢。因此我们需要一些函数来解决一些对应的问题。函数式编程更多的是关心数据的映射,更简单的来说,就是只关心数据处理的结果,而不是数据处理的过程。它是通过声明纯函数的方式,在不修改原始数据的情况下的一种编程范式。它可以通过类似指针的方式实现高阶函数,且不会破坏原始数据的完整性,使得它在编程领域得到了广泛的应用。
3、前端中的响应式编程代表库RXJS
rxjs是前端响应式编程的代表库,是观察者模式、迭代器模式、函数式编程的结合体。他是angular2.0+以上版本的集成库,它同promise一样也是观察者模式的js实现。 下面来对比一下promise 、async、rxjs。
对个人而言rxjs以流的形式来编程,通过管道的形式来控制流,管道中又有很多的聚合函数,方便开发者使用,从而大大的提高了开发的效率。但是从项目的难易程度来说,rxjs更适合处理一写复杂的异步事件流,对于一些单一的异步事件,promise及async/await 及相应的库,已经能满足我们开发需求,而不必要去引入新的库。
总结:前端异步编程中我们整理这这么多关于异步编程的实现方案,我们可以根据自己的需求采用不同的方案来完成自己的目标。每一种实现方案都有它自己的解决问题的领域,我们应该更多的去理解方案的优越性与弊端,从而挑选出更为适合的解决方案,在前人的基础上,发挥个人的扩展空间,在解决实际问题是手到擒来。
下一篇:前端中的面向对象编程(一篇)