落园 » Shiny的架构浅析|专注经济视角下的互联网

Shiny的架构浅析

不是说学一门语言学的不仅仅是他的语法,更重要的是他背后的思想么?R本身是个大杂烩,ggplot可以单独拎出来作为一门语言学,shiny其实也可以单独拎出来学一番。

只是简单的实现一个shiny app确实不难,就像官网上一进去看到的那个例子那样。基本上如果只是做一些比较简单的可控的dashboard,shiny的代码无非就是写的细致一点,谈不上什么架构之类的。

直到某一天...你发现这东西还可以玩的更深,然后就毅然跳入了下一个大坑——shiny reactivity。官网的开场白很直接

It’s easy to build interactive applications with Shiny, but to get the most out of it, you’ll need to understand the reactive programming model used by Shiny.

然后就介绍三剑客:reactive sources, reactive conductors, and reactive endpoints。

最简单的情况:没有conductor,直接从source到endpoint。

继续拷贝官网图:

嗯,听起来不难...其实大部分情况下shiny app处理的都是这样的情况。基本上就是一个输入(input)和输出(output)的过程。最简单的,就是我们经常在shiny app里面需要处理的input对象,会读入各种用户操作带来的值,然后后面返回一个表格或者图或者文字什么的。回到官网的例子(继续拷贝官网图)

大概就是这么一个简单的架构。在这种架构下,自然可以写很多if else之类的在server.R中加入各种各样输入输出的组合,然后在ui.R中排列一下输入的各种框框和输出的各种图标文字什么的。

考虑conductors的情况

shiny用的稍稍熟悉了,就开始想更多的控制这个东西。其实conductor说白了有点中间变量的感觉,就是他本身并不会最终显示出来,但是作为一个中间过程存在着。比如官网一个计算Fibonacci 序列的例子:

这里无非就是多了一个新的对象currentFib(跟input和output都无关),暂时的存储了一下计算过程中的变量,然后基于这个东西,又衍生了两个最终显示出来的返回值。新的架构图就多了一个conductor这样。

再复杂一点:考虑Reactive expressions

按照官网的说法,这个东西包括:

  • accessing a database
  • reading data from a file
  • downloading data over the network
  • performing an expensive computation

基本就是从其他的数据源而不是用户的input那里读数据的情况。常见的场景比如,按照用户给定的一些条件(由input传入),返回一个符合条件的数据子集。如果数据全集是会不断更新的(比如每次都应该重新load("xxx.rdata")这样),那么这个这句话就必须写在reactive里面。同理,如果直接利用input生成一句SQL然后连接数据库读取数据,那么也要写在reactive里面。

再复杂一点:自动还是手动更新

shiny默认的情况下,如果没有放submit按钮,那么就是随便一个操作就trigger整个reactive的流程。比如官网首页上,我们拖拖鼠标那个直方图就跟着变化。如果不想让他直接变化,那么简单的可以放一个submit按钮,然后只有submit之后才会变化。

如果希望更好的控制一个app界面上各个部分呢?就要动用更高级一点的actionButton

这东西还要配合一个isolate(),就是你要告诉shiny哪些东西跟着这个button变化,哪些不属于这个button的控制范围。比如官网的例子:

这里只有goButton被点击的时候,才会执行下面的抽随机数并画图。actionButton是随着每次点击而不断增加计数的,从0开始一直增加过去,所以可以在server.R里面利用这个button的返回值来进行流程控制。

篇外废话:

shiny有希望成长成一个可以替代php这样实现客户端和服务器端大部分交互请求的巨人么?从这点来看,Tableau还是限制太多了。


Comments

Leave a Reply

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