- 浏览: 16493591 次
- 性别:
- 来自: 济南
最新评论
-
wu1236:
ef0793cd94337324b6fefc4c9474af5 ...
Android ApiDemos示例解析(87):Media->MediaPlayer -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
本博客文章都为转载,没有任何版权! -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
VPLEX - EMC的RAC -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
qTip2 Show -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
SecureCRT中文乱码、复制粘贴乱码解决办法(修改版)
JavaScript 中的有限状态机
JavaScript 中的有限状态机,第 1 部分: 设计一个小部件使用 JavaScript 和有限状态机开发浏览器应用程序 |
级别: 初级 Edward J Pring (pring@us.ibm.com ), Senior Software Engineer, IBM 2007 年 1 月 29 日 <!-- START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --> <!-- END RESERVED FOR FUTURE USE INCLUDE FILES-->
多年以来,Web 设计人员一直都通过在流行的 Web 浏览器内采用 JavaScript 解释器的方式来改善其网站的外观。他们的做法大都是将代码的简短片段复制到 HTML 页面中。当前,随着 Ajax 的日益流行,软件工程师也开始使用 JavaScript 来开发能在浏览器内执行的新一代的应用程序。基于浏览器的应用程序的规模不断扩大,这就相应要求采用其他执行环境成长和发展所使用的相同设计模式和开发原理。
基于浏览器的应用程序在实时环境中执行,在这种环境中鼠标、键盘、定时器、网络和程序事件都十分常见。当事件驱动的应用程序的行为取决于事件发生的顺序时,其编程就会变得非常复杂,也十分难以调试和修改。软件工程师早已开始使用 有限状态机 —— 学术领域有时又称其为离散或确定性有限自动机 —— 作为一种组织原理来开发事件驱动的程序了。 有限状态机通过用直观的表格代替复杂的逻辑为设计增加了严密性。从传统意义上讲,有限状态机对开发诸如网络驱动程序和编译器这类程序颇有帮助。有限状态机也同样有助于开发基于浏览器的应用程序。 在本系列中,您将练习开发一个样例有限状态机应用程序,来深入体验 JavaScript 语言的一些独特特性:
这些语言特性可以提供一种紧凑而简明的方式来为状态间的事件和转移组织动作,还可以提供一种巧妙的方式来兼容不同的浏览器事件模型。 样例应用程序 FadingTooltip 比内置于大多数浏览器的默认工具提示更为精致。用 FadingTooltip 小部件创建的工具提示使用动画式淡入和淡出代替突然弹出和消失,并可随光标移动。设计此行为所用的有限状态机模式使逻辑清晰透明。实现此行为所用的 JavaScript 语言特性则使源代码紧凑而有效。 本文展示了如何使用有限状态机的图、表表示设计一个动画式小部件的行为。本系列的后续文章会介绍如何在 JavaScript 内实现有限状态机的表表示以及如何处理与在流行的浏览器内进行测试和实现相关的实际问题。 当 光标暂时停留于一些可视控件 —— 比如按钮、选择器或输入字段 —— 时,时下的许多图形应用程序都能暂时显示包含相应的帮助性定义、操作说明或建议的小文本框。在早期的系统中,这些小文本框被称为 “气球帮助”,在 IBM 的一些产品中,称其为 infopop,在一些 Microsoft 产品中,其名字则是 ScreenTip。在本文,我使用的是其中更为常见的术语工具提示 。 现在一些流行的 Web 浏览器,比如 Netscape Navigator、Microsoft Internet
Explorer、Opera 和 Mozilla Firefox,会为任何拥有 清单 1. 浏览器工具提示的 HTML 代码
样例页面
展示了浏览器如何呈现具有 内 置的工具提示还有很多可待提高之处,一些流行浏览器的最新版本为构建更为精致的工具提示提供了所需的 “原料”。HTML Division 元素创建了一个可在浏览器窗口的任何地方放置的提示框。通过级联样式表(CSS),您几乎可以设定框体外观的各个方面。用 JavaScript 编程实现的光标移动可以触发浏览器窗口内任意可视元素的特定动作。您还可以编制一个定时器来控制这些动作的顺序。 在 样例页面 可以找到具有这类工具提示的一些 HTML 元素。如果运行的是流行浏览器的最新版本,您就可以将更为精致的工具提示和内置的工具提示做一对比:
这 些增强的行为和外观不仅有修饰的作用,还可以提高可用性。面对有数十个或数百个元素的繁忙页面,用户很可能会错过即刻弹出的工具提示。人类的视觉系统对运 动的物体十分敏感,因而也更容易注意到淡入视野并随鼠标而动的工具提示,即使用户的注意力不在这儿也没关系。对比未格式化过的文本,图像、格式化和样式化 能更有效地传递信息。而且,这些更为精致的工具提示的所有参数都是可配置的。 本文后面的内容将着重于介绍如何将 FadingTooltip 小部件设计为一个有限状态机。本系列的后续文章会为您展示如何实现和测试这些代码。如果您急于想知道这些代码,也可以在 参考资料 部分找到到相关 JavaScript 源代码和使用这些代码的一个 HTML Web 页面的链接。
有限状态机对行为建模,在该模型中,对将来事件的响应取决于先前的事件。此领域已出现了大量学术著作(参见 参考资料 ),而有限状态机的实用定义却十分简单明了。有限状态机就是包含如下内容的计算机程序:
在行为由许多不同类型事件驱动以及对特定事件的响应取决于先前事件发生顺序的情况下,有限状态机最为有用。 驱动有限状态机的事件可以是计算机外部的(由键盘、鼠标、定时器或网络活动发起),也可以是计算机内部的(由本应用程序的其他部分或其他应用程序发起)。 状态是记起先前事件的一种方式,转移则用来组织对将来事件的响应。其中的一个状态必须要被指派为初始状态。结束状态可有可无,FadingTooltip 小部件就没有结束状态。 有限状态机的两种常见表示为: 用 有限状态机开发事件驱动程序比一般的过程式编程要复杂一些;一般来说,需要更多的规则,尤其是更多的设计精力。如果处理得当,有限状态机可以使代码简单、 测试迅速、维护轻松。但是,即便如此,有限状态机的复杂性使其并不能适合所有事件驱动的程序的开发。例如,当事件的种类不多或事件触发的动作总是相同时, 进行额外的开发可能会得不偿失。
有限状态机是事件驱动的,需要在它们的运行时环境将其与其相关的事件挂接起来。这可通过事件处理程序 实现,事件处理程序是一些可插入到运行时环境的小的代码片段,一旦特定事件发生,这些处理程序就会执行。事件处理程序执行时,需要获得如下一些基本信息:
JavaScript 十分适合于构建事件驱动的有限状态机。事实上,JavaScript 有点太过适合 —— 它有三种挂接事件的方式。每种事件模型 都很直观明了,但程序必须实现所有三种模型以确保它们可以运行于所有流行的浏览器之上。事件的上下文在其中两个事件模型内被直接传递给事件处理程序;对于另外一个模型,JavaScript 函数闭包允许事件的上下文被包裹进其事件处理程序。 JavaScript 提供一种对象模型 ,对象模型是 Java 和 C++ 程序员所熟知的,它也可用来对有限状态机的变量和方法进行编码。而且,JavaScript 关联数组还允许直接对有限状态机的二维表进行编码。
有限状态机的基本要素是它所响应的事件及事件间的状态。设计必须考虑到每个可能状态的每个可能事件:
我以 图 1 所示的一个图形来开始设计的过程,图中气球形圆圈所示的是状态,连接这些圆圈的箭头线代表的是转移。最终获得的是一张表,如 图 4 所示,在该表的标题行和标题列分别列出了事件和状态。表中的一些单元格列出了当特定事件在特定状态发生时所要执行的动作,其它一些则表示在该状态下此事件不能发生。 通 常,需要反复执行此设计过程才能获得正确的图和表。对具有多个事件和状态的有限状态机,这个过程可能会十分乏味,每次重复都需要遵守一定的原则来系统地处 理表中的每一个单元格。这迫使您不得不考虑在每个可能的情况下您所想要的动作。您可能会发现还可以进一步完善这些行为,也可能会发现所需的状态较预计的要 多(或少),甚至会发现您必须重新整理单元格间的这些动作以正确定义每种情况下的行为。 这种设计有限状态机的系统过程虽然有些乏味但却十分值得。图 4 所示的完成后的表给出了此行动的所有逻辑,并可被直接转换为代码(参见 actionTransitionFunctions 源代码)。
要设计 FadingTooltip 小部件,您需要了解 JavaScript 的一些功能。在严谨设计的原则指导下,我只在这里给出基本的设计思想,而将具体的实现留待本系列后续文章中介绍。 当光标经过页面中的 HTML 元素时,所有流行的浏览器都能将事件传递给 JavaScript 代码。这些事件是 mouseover 、mousemove 和 mouseout ,分别代表光标已经移至、移上和移出 HTML 元素。浏览器用这些事件传递光标当前位置。当事件发生时,可用 JavaScript 编程动态创建 HTML Division 元素,用文本、图像和标记填充这些元素并将其定位到光标附近。 浏览器并没有原生的淡入和淡出函数,但可以通过改变 Division 元素的透明度(实际上是不透明度,透明度的反义词)来模拟这些函数。 JavaScript 有两类定时器:一次定时器在超时时生成 timeout 事件;重复断续器定期生成 timetick 事件。FadingTooltip 小部件需要这两种定时器。
首先回顾一下想要从 FadingTooltip 小部件获得的基本行为。当光标从特定的 HTML 元素上移过的时候,您可能想让此小部件等待光标在该元素上暂停。如果可以如此,之后您可能又想让此小部件将工具提示淡入,显示一会后再淡出。 有限状态机将需要响应以下事件:
您 将需要设计状态机在事件间等待的一些状态。需要调用小部件的初始状态 Inactive,小部件在该状态下等待被 mouseover 事件激活。小部件在 Pause 状态下等待直到 timeout 事件指示光标已经在 HTML 元素上停留了足够长的时间。之后在用 timetick 事件动画式淡入的同时,小部件会在 FadeIn 状态下等待,继而又会在 Display 状态等待另一个 timeout 事件。最后,在用更多 timetick 事件动画式淡出的同时,小部件会在 FadeOut 状态下等待。小部件转回到 Inactive 状态,在此状态下等待另一个 mouseover 事件。 图 1 是此过程相应的图形表示,其中的气球形圆圈代表状态,连接圆圈的箭头线代表转移,箭头线上的标注代表事件。双层边界的圆圈代表初始状态。 图 1. 状态图的初始设计 FadingTooltip 小部件必须针对它处理的每个事件采取动作:
图 2 在触发这些动作的事件之下列出了这些动作。 图 2. 在初始状态图的事件下追加动作
上述的状态图是设计有限状态机的一个很好的开始。但表形式更适合于完成设计,原因是表可以给出事件和状态的所有组合以供参考。 要将状态图转换成状态表,可以在行标题内填上事件名,在列标题内填上状态名。这些名字的顺序是任意的;我在第一行的开始位置放入了初始状态,在第一列的开始位置放入了初始事件,随后将动作和每一事件的下一状态复制到表中适当的单元格内,如 图 3 所示。 图 3. 与初始状态图对应的初始状态表
要完成有限状态机的设计,需要顾及表中的每一个空单元格。您需要为每个单元格做这样的考虑:该事件是否可以发生在该状态,如果可以,小部件在这种情况下将采取什么动作,下一个状态又将是什么。这虽然有些乏味,但却是设计过程的必需部分。 考 虑单元格的顺序先后关系不大。通常在设计过程中需要多次重复此步骤,反复考虑每个单元格,不时地修改其内容,而且每次的考虑顺序都会有所不同。另外随着设 计的不断深入,添加(或删除)状态、做进一步的修改也十分常见。在这里,我将跳过这些反复过程,着重总结如何通过依次查看每个状态和事件来获得最终的结果 表。 在继续之前,还应注意一下此状态的 mouseover 事件。当为此工具提示创建 HTML Division 元素时,需要将它定位于光标的附近,所以要保存光标的当前位置,当前位置由浏览器与此事件一同传递。而且在开始新的定时器之前,最好能够取消任何运行着的定时器。在 mouseover 对应的单元格内添加上述动作。 在 等待定时器超时时,光标可能会在 HTML 元素内移动或从此 HTML 元素移出。需要决定一旦发生这些事件所应采取的动作以及下一个状态是什么。如果在此状态发生 mouseout 事件,FadingTooltip 小部件应能返回 Inactive 状态,就像光标从未经过 HTML 元素一样,而且还必须取消定时器。在 mouseout 对应的单元格记录这些动作和转移。 另一方面,对于 mousemove 事件,则需要小部件能够继续等待光标悬停,这又要求取消和重新开启定时器。因为想要让工具提示出现在光标的附近,所以需要更新所保存的光标位置。 Pause 状态下的 mousemove 事件的动作和转移与 Inactive 状态下的 mousemove 事件的动作和转移相同。所以无需重复两个单元格的内容,在 mousemove 对应的单元格内放上同样的内容即可。将此列的所有其他单元格标记为“不应发生”。 不要将此单元格标记为“不应发生”,而是应该标示为无需任何动作。如果光标又再次回到该 HTML 元素,将工具提示移回光标并返回 FadeIn 状态。 图 4 显示了所有这些动作和转移。剩下的空白单元格应标记为“不应发生”。 图 4. FadingTooltip 小部件设计后的状态表 有限状态机的状态表总是能转换回状态图,因为二者是等价的。图 5 显示了完整的状态表对应的状态图。 图 5. FadingTooltip 小部件设计后的状态图
完成状态表和状态图之后,很有必要对它再进行一次回顾来收集状态机在两事件间需要记录的变量以便状态机能够执行不同的单元格内的相应动作。有限状态机需要 清单 2 中所示的状态变量。 清单 2.初始的状态变量列表
虽然 JavaScript 变量本身不区分类型,但变量所包含的值是区分类型的(这就是说,任何类型的值都可以赋给变量)。根据这一原则,我列出了状态变量名并在注释部分给出了希望赋给这些变量的值的类型。
有了完整的状态表和状态变量之后,就可以实现有限状态机了。本系列的下一篇文章将重点介绍实现过程,敬请关注。不过请记住开发是个反复的过程,有时您可能需要返回设计阶段。 下载
学习
获得产品和技术
讨论
|
相关推荐
1. **状态定义**:在有限状态机中,每个状态都是系统可处的明确条件。例如,在用户登录系统中,状态可能包括“未登录”、“正在登录”、“已登录”等。开发者需要先定义好所有可能的状态,并为每个状态赋予特定的...
javascript中有限状态机的最小(neto)实现 网络工作者 例子 贡献 作者 执照 发布 请报告任何错误或功能请求,谢谢! 概述 生成有限状态机。 可以定义状态,可以执行到这些状态的转换,并且可以传递动作的参数。 ...
JavaScript 与有限状态机(Finite-state machine)的概念在软件开发中具有重要的应用,尤其是在处理复杂的逻辑和异步操作时。有限状态机是一种数学模型,它通过定义一系列的状态和状态之间的转换来描述系统的运行...
然而,"Nsynjs"是一个独特的JavaScript执行引擎,它引入了一种新的概念——状态机,这使得开发者能够以同步的方式编写代码,即使在异步环境中。 状态机是一种计算模型,它通过在不同状态之间转移来处理输入和执行...
用于TypeScript和JavaScript的可执行有限状态机。 如果您喜欢@ steelbreeze / state,请给它加注星标... 注意: v8现在可以使用,并且包含重大更改,但是可以进一步简化代码库的性能。 有关更多信息,请参见。 ...
图灵机状态机是一种基于规则的状态转换系统,可以用来解决特定的计算问题。在这个项目中,我们看到一个用JavaScript实现的图灵机,它专注于识别"abcd"序列。JavaScript是一种广泛使用的编程语言,尤其在网络前端开发...
在JavaScript的世界里,状态机(Finite State Machine,FSM)是一种设计模式,它用来描述一个对象在生命周期中可能经历的一系列状态以及这些状态之间的转换。这个"使用ES6 Promise实现的一个无限状态机"是一个创新的...
JavaScript Finite State Machine(JSFSM)是一个专门为JavaScript编程语言设计的独立库,它实现了有限状态机(Finite State Machine,FSM)的概念。有限状态机是一种数学模型,常用于描述和控制程序的不同行为阶段...
- 在分层状态机中,状态间的转换可能跨越不同的层次,增加了灵活性。 4. **State.ts**: - 这个文件很可能是状态机的核心实现,包含了状态类或者状态接口,定义了各个状态以及它们之间的转换规则。 - 可能会包含...
为了更深入地利用有限状态机,在JavaScript中,我们可以使用诸如JavascriptFiniteStateMachine这样的库来简化状态机的定义和管理。这些库提供的函数和接口能够使状态机的实现更加规范和高效。例如,使用StateMachine...
在JavaScript中,有限状态机设计模式是一种强大的工具,它可以帮助开发者更好地组织代码,确保程序在任何时刻都处于一个清晰定义的状态,从而减少错误并提高可维护性。 在JavaScript中实现有限状态机,通常涉及到...
实现有限状态机的 JavaScript 库 您可以轻松定义状态和事件,例如 STATE = { S1 : "State 1", S2 : "State 2" }; EVENT = { E1 : "Event 1", E2 : "Event 2" }; 然后通过声明初始状态(又名入口点)来实例化一...
在JavaScript编程中,有限状态机(Finite State Machine, FSM)是一种设计模式,它将系统的行为定义为一组状态,以及在不同状态之间转换的规则。这种模式在处理复杂逻辑和流程控制时非常有用,特别是在事件驱动的...
1. **状态**:在有限状态机中,每个状态代表了对象的一种行为模式或条件。例如,一个按钮可能有“禁用”、“启用”和“加载”等状态。在`fsm.js`中,开发者可以通过库提供的API来定义这些状态。 2. **事件**:事件...
本文内容包括:有限状态机有限状态机和运行时环境系统地设计行为关于JavaScript设计状态图将状态图转换成状态表完成状态表收集状态变量结束语下载参考资料有限状态机很早就已用作设计和实现事件驱动的程序(比如网络...