首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用 continuation 开发复杂的 Web 应用程序(2)continuation 的适用场合

用 continuation 开发复杂的 Web 应用程序(2)continuation 的适用场合

continuation 的适用场合基于 continuation 的 Web 应用程序巧妙地避开了上面提到的与 Web 应用程序开发有关的问题。比起基于 MVC 的 Web 应用程序,基于 continuation 的应用程序是作为一个程序编写的。每当程序需要从用户得到输入的时候,就会把包含相应表单的 Web 页面发送回用户的浏览器,并生成代表应用程序逻辑        剩余部分的 continuation,并把它放在一边。(我很快就向您解释把 continuation  "放在一边" 的选项)。因为重要的事是在接收到用户的响应时能够重新开始应用程序逻辑的剩余部分,所以还要为服务器生成了一个惟一的         id,作为在         continuation 存储库中搜索特定 continuation 的键。这个         id用某种适当的方式和显示给用户的页面一起也向后发送,这样表单提交会使         id在响应中发送回来。     
还记得阻塞 I/O 吗?本文中描述的方法在一个典型的读写程序中使用(或者与所用语言中的           read和          write等价)continuation。概括来说:对           read的调用使应用程序阻塞,只有在用户提供了输入之后才继续。提供的输入被用来继续应用程序逻辑。任何中间输出则通过非阻塞的           write调用显示给用户。下次程序要求用户输入信息的时候,它会进行另外一个           read调用,并再次阻塞。这个序列持续进行,直到程序结束。      
重要的是要注意:基于 continuation 的程序与使用阻塞读写的独立程序没什么不同。所有通常的编程结构都可以使用,包括基于           if条件的分支、           for和           while循环,甚至更多。惟一的区别是:在 MVC 模型中,使用这些结构的应用程序代码有可能分散到多个不同模块和页面中,但是在基于 continuation 的程序中,整个逻辑包含在一个程序中。      

当必要的响应从用户到达,服务器(为部署的 Web 应用程序提供 continuation 的基础设施)在响应中检索 continuation 的         id(与正常提交的数据一起),并用这个         id在存储库中检索 continuation 。然后就继续执行 continuation(也就是说,应用程序逻辑在紧接着创建 continuation 的代码之后开始执行)。通常,前几行会提取用户提交的数据的剩余部分,这意味着在程序中服务器必须能够访问请求对象,而业务逻辑会用接收到的数据继续进行。     
在继续执行 continuation 时,启动执行的代码可能要求用户输入更多数据,所以需要进一步交互。处理方法是创建第二个 continuation,把它保存在 continuation 存储库,并把嵌入了适当 continuation         id的表单发送给用户。可以把生成的        外部(outer)和        内部(inner)continuation 看作一个树结构,外部 continuation 作为父节点,内部 continuation 作为子节点。与此类似,如果业务逻辑有条件分支代码(根据         if子句的结果有不同的动作),针对每个分支发送回浏览器的数据搜集页面可能是不同的,因此会针对每个分支形成对应的 continuation,每个 continuation 都是外部 continuation 的子节点,而彼此之间则是兄弟节点。按照这种方式,可以把完整的应用程序看成是与 continuation 树对应 ——         continuation 的森林。     
以用户为中心的导航从外部来看,无法区分基于 continuation 的方法和 MVC 架构。客户仍然可以自由地返回前面已经提交的 Web 页面,修改必要的数据,然后通过浏览器再次提交表单。区别在于内部,在于为了让导航正确工作需要耗费的代码数量。基于 continuation 的方法不需要额外费力处理正确导航,因为每个提交的表单,都会有一个 continuation         id与之关联。服务器只需要查看某个提交页面的正确 continuation,就可以要求它继续执行。     
假设用户正在查看页面。按照所谓的         continuation 树的术语来说,这个页面用某个 "continuation 节点" 进行了 " 标记" 。如果用户单击 Back 按钮返回到前面已经提交的页面,那么 continuation 树中的标识器就会向上移动一级,并把指针设置到这个节点的父结点。每次用户单击 Back 时,continuation 树中的移动就会发生一次。现在假设用户停在某个页面上,重新输入数据,新输入的数据可能与以前在这个页面中输入的数据相同,也可能不同,然后用户重新提交表单。这使 continuation 树中的标识器向下移动一级,指向子节点。但是,因为应用程序逻辑根据新提交的数据可能要显示不同的页面,所以现在的子节点实际可能是上一次移动中标识器指向的子节点的兄弟节点。按照同样的逻辑继续执行,在树中,后退的路径可能会遇到不同的一套 continuation,也可能遇到相同的,具体情况取决于用户提交的数据。     
规则由您定!虽然有可能把 continuation 作为一个更简单的 MVC 框架替代品来实现,但是这种编程风格确实提供了一些独一无二的优势,特别是当它控制应用程序行为的时候。例如,支持 continuation 的框架通常允许使某个 continuation 无效。使某个 continuation 无效会导致无法返回与它对应的页面(例如,单击浏览器的 Back 按钮),并在重新提交表单之前修改关联的表单数据。(在系统内部,服务器删除了与指定 continuation         id对应的 continuation 对象)。结果,要继续执行操作却没有 continuation 可用,所以就会报告错误。这个错误可以用正在使用的开发框架的特定方式进行处理,例如,把浏览器重定向到出错页面。在某些情况下,排除这些动作,会对您的应用程序的处理开支提供更高层次的控制。正如前面讨论过的,有可能在 MVC 框架中使用脚本代码来禁止某些导航模式。continuation 恰恰可以让您更容易地这样做。     
与 MVC 的实现不同,对于为了处理克隆而造成的代码混乱,基于 continuation 的技术提供了一个解决这个混乱的迂回解决方案。在基于 continuation 的技术中,用户可以在原来的窗口或克隆的窗口中输入不同的数据,把二者并行提交。然后在两个线程中(基本上,是分配给处理两个请求的服务器线程)用提交的两套数据继续执行 continuation。对于不是基于 continuation 的应用程序来说,这是经常发生的,而这个输出更合适一些:要么禁用这类特性,要么使用一个事务覆盖另一个事务。禁用这个特性通常不是一个好的选择,因为用户有时会用浏览器的克隆特性,对先后选择的两套数据进行对照分析。
还值得注意的是:基于 continuation 的方法消除了用户状态的概念。使用 continuation,用户在同一时间可以有多个状态,每个状态对应浏览器窗口中的一个克隆页面。
返回列表