R Shiny 中文文档4.1-响应式编程概述

八月 26, 2014 R, web开发, 可视化, 编程开发 por DeanGao

在之前的章节中我们可以看到在Shiny能够轻松地创建一个响应式应用程序,对Shiny中德响应式编程也有一个初步的了解,现在我们来具体了解下是如何工作的。


转载请注明出处:网址+邮箱:
例如: 转自 
http://www.iwhgao.com (gaowenhui2012@gmail.com)


在Shiny的响应式编程中,有三种对象:响应源(reactive sources)、响应操作者(reactive conductors)和响应终结(reactive endpoints),可以用下面的三种图形代表:

roles

首先来讲解下最简单的响应式编程

响应源到响应终结

下面图示最简单的响应式编程结构:

simplest

再来讲下哪些被认为是响应源和响应终结。你可能也有个初步的认识了,在Shiny中一般的来自于用户浏览器界面操作的输入结果就是响应源,而对应的由服务器端传递到客户端的内容是响应终结,像plot table等。所以通俗的理解就是input为响应源,output为响应终结(实际上还有些其它类型的响应终结)。

例如下面的具体例子:

input$obs即为用户的操作输入,即响应源,而output$displot为服务器端向客户端输出的内容,即响应终结。所以当响应源input$obs发生了改变后,output$displot就响应的输出新的结果。如果有其它GUI开发的经验的话(像Java开发一些客户端),都是有对应的事件响应机制来处理这些改变的,但是在Shiny中,这些操作对用户来说都是透明的,用户不用去关心底层的具体实现,而可以主要去关心常规的R编程。以此类推,同一个响应源也可以被多个响应终结所接收而做出对应的改变,例如下面的例子:

图示:

faithful

 

input$individualObs 就被output$plotOut 和 output$tableOut同时捕获。

响应操作者

在上面介绍了响应源是如何直接的作用于响应终结后,这部分讲下响应源是如何经过中间的操作者而间接的被响应终结而捕获,所以介于响应源和响应终结间的组件就是响应操作者。一个操作者可以是一个附属物也可以拥有附属物,简单的说就是在一个响应式编程的示意图中响应操作者可以是一个父节点也可以是子节点,但是响应源只能是父节点(可以拥有子节点),而响应终结只能是子节点。

响应操作者可以用来包裹那些允许慢或者需要大量计算的操作。举个例子(其实在之前的概述中讲过响应式表达式,就是这样的),如下所示:

利用递归的方式来算Fibonacci 数列是有一些时间开销的,是低效率的,但数值比较大时更加明显。再看上面的这个例子, 没当n改变时,fib函数都要被执行两次,而且是同样的结果,所以另外一次的计算是没有必要的。它的示意图如下:

fib_no_conductor

如何去避免这种没有必要的时间消耗呢?这里就引进响应操作者来优化。

示意图:

conductor

 

Ps: 这里需要记住的一点是, 响应式的“世界”或者作用域可以看见和改变非响应式的“世界”,但是反过来就不行,所以在响应式编程中代码的位置很重要。我们来看看下面的代码:

错误提示:

即renderText响应式的函数(“世界”)不允许包含一个不是响应内容的代码,就是currentFib不是响应式表达式也不再render*系列函数内部,所以会引发错误。简单的说就是当n改变的时候 nthValue不会做出相应的响应。

所以,这里改下即可,两种方法:

1. 响应式表达式

2. 写在render*系列函数内部

3. 或者写成函数式

我们现在再来终结下:

在响应式编程中有以下几个关键概念:

1. 响应源(reactive sources) 能够向下游的对象传递信号,让它们重新执行

2. 响应操作者(reactive conductors) 位于响应源和响应终结之间。通常是用于耗时长的计算

3. 响应终结(reactive endpoints)能够根据响应式环境来重新执行,也可以请求上游对象执行

4. 无效的肩头(invalidation arrows)指明一些无效的事件(例如上面的例子)

 

响应源、响应操作者、响应终结的具体实现–值(values)、表达式(expressions)、观察者(observers):

1. 值(reactive values) 即是响应源的具体实现  。通常是客户端的input 对象

2. 表达式(reactive expressions) 代表响应操作者,它们通常能够访问值或者其它的表达式,最后有一个返回值供后者使用。通常用于一些耗时较长的计算中或者避免没必要的重复计算中,比如:

>访问数据库

>从文件读取数据

>从网络中下载数据

>耗时长的计算

3. 观察者 (observers)代表响应终结,它们可以直接访问值或者通过表达式间接的访问值。通常是output对象及其render*系列函数

 

下面的这个示意图可以很好的对应:

roles_implement

响应时表达式与观察者间的差别:

1. 观察者是对响应式的刷新事件进行响应,但是响应式表达式不是。所以如果想要一个响应式表达式能够被执行,那么它必须被一个观察者所包裹;

2. 响应式表达式能够返回值,但是观察者不能。

原创文章,转载请注明: 转载自deangao's blog
本文链接地址: R Shiny 中文文档4.1-响应式编程概述