将窗口抽象想象为函数调用:如果能让所有窗口都表现为”纯函数”,就能解决同步问题。
// 理想状态:窗口 = 纯函数
Window(userActions) => UIState
// 纯函数特性:相同输入 → 相同输出
Window(actions) === Window(actions) // 总是为 true
如果窗口表现为纯函数,用户输入行为对应存函数入参,传入相同入参执行后可以得到完全一致的页面输出,从而实现多个窗口效果同步。
然后,事实是副作用无处不在:
副作用产生的不确定性,导致相同入参调用还是会产生不同结果。
举例来说🌰:
const [uuid, setUuid] = useState();
<div onClick={handleTest}>button--{uuid}</div>
function handleTest() {
const newUuid = getUuid();
console.log(newUuid);
setUuid(newUuid)
}
哪怕俩个窗口都触发调用 handleTest 方法,界面展示会因为 Uuid 的随机性出现差异化。
什么是副作用归一化?
副作用归一化 = 让”不确定操作”变成”确定操作”
简单来说:由一个窗口先执行完整流程期间自动收集对应副作用结果,其他窗口执行相同操作副作用计算从记录中获取副作用结果,而不重新计算结果。
Leader窗口(发起):用户操作 → (执行副作用 → 收集结果 → 缓存)[劫持] → 同步
Other窗口(同步):用户操作 → (劫持副作用 → 从记录获取)[劫持] → 使用结果
副作用归一化难点: