大家好,我是每天坚持一点点的铁蛋儿,一个爱分享前端的老body。这篇是分享手写状态机,大家务必点赞
、收藏
保存一下慢慢看,你们的关注
是我更新的动力。
相关学习资源
本系列有配套视频
,大家学习同时千万不要忘了三连
+ 关注
+ 分享
,有道是喝水不忘挖井人~
- HTTP基础原理:【HTTP基础原理视频】
- HTTP加密算法: 【HTTP加密算法视频】(视频更新中... 着急的小小伙伴先收藏哈)
- 大厂高频面试真题:【大厂面试高频面试解题视频】
- Vdom和diff算法:【轻松搞定vdom和diff视频】
当我们在学习Vuex、Redux、Pinia的时候 “状态机”这个词时不时的会出现一下。虽然咱们不是计算机科学家,但是对于这样的计算机理论方面的词汇还是要有基本理解的。
1. 定义
状态机的基本定义。一句话:
状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。
先来解释什么是“状态”( State )。现实事物是有不同状态的,例如一个自动门,就有 open 和 closed 两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有限个,例如自动门的状态就是两个 open 和 closed 。
状态机,也就是 State Machine ,不是指一台实际机器,而是指一个数学模型。说白了,一般就是指一张状态转换图。例如,根据自动门的运行规则,我们可以抽象出下面这么一个图。
自动门有两个状态,open 和 closed ,closed 状态下,如果读取开门信号,那么状态就会切换为 open 。open 状态下如果读取关门信号,状态就会切换为 closed 。
状态机的全称是有限状态自动机,自动两个字也是包含重要含义的。给定一个状态机,同时给定它的当前状态以及输入,那么输出状态时可以明确的运算出来的。例如对于自动门,给定初始状态 closed ,给定输入“开门”,那么下一个状态时可以运算出来的。
这样状态机的基本定义我们就介绍完毕了。
重复一下:状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。
四大概念
下面来给出状态机的四大概念。
第一个是 State ,状态。一个状态机至少要包含两个状态。例如上面自动门的例子,有 open 和 closed 两个状态。
第二个是 Event ,事件。事件就是执行某个操作的触发条件或者口令。对于自动门,“按下开门按钮”就是一个事件。
第三个是 Action ,动作。事件发生以后要执行动作。例如事件是“按开门按钮”,动作是“开门”。编程的时候,一个 Action 一般就对应一个函数。
第四个是 Transition ,变换。也就是从一个状态变化为另一个状态。例如“开门过程”就是一个变换
好了废话说完了,直接上代码。
2. 实现状态的依赖收集
为了方便流的管理使用Rx.js管理,不熟悉的Rx.js的小伙伴可以去看下官网
- 实现状态收集
import { Observable } from 'rxjs'
type ObservableFunction = (data: any) => void
export class Emiter<Topic extends string | number>{
private observers: Map<Topic, ObservableFunction[]>
constructor() {
this.observers = new Map()
}
private addObserverFunction(topic: Topic, fn: ObservableFunction) {
if (!this.observers.has(topic)) {
this.observers.set(topic, [])
}
this.observers.get(topic)?.push(fn)
}
// 收集
on(topic: Topic | Topic[]): Observable<any> {
return new Observable<any>((observer) => {
if (Array.isArray(topic)) {
topic.forEach(t => {
this.addObserverFunction(t, (data) => {
observer.next(data)
})
})
} else {
this.addObserverFunction(topic, (data) => {
observer.next(data)
})
}
})
}
// 发射
emit(topic: Topic, data?: any) {
this.observers.get(topic)?.forEach(fn => {
fn(data)
})
}
}
- 使用
// 用例
enum Topics {
A,
B,
C
}
const emitter = new Emiter<Topics>()
emitter.on(Topics.B).subscribe((data) => {
console.log('a', data)
})
emitter.emit(Topics.B, '我是传过来的铁蛋儿')
3.未完待续。。。
我是每天坚持进步一点点的铁蛋儿,如果你对技术有像一素的偏执,欢迎vx:15910703837一起学习一起进步。