是这样的,这天,我接到了一个 BUG,当然这个 BUG 不是我写的,是这样的有两个页面:
- 页面 A:有同步代码,有异步代码
- 页面 B:全是同步代码
注意:此项目是老项目,没有全局状态管理工具!!!
// 页面A
console.log(1)
console.log(2)
http.get(url).then(res => {
console.log(3)
localStorage.setItem(key, res)
})
// 页面B
console.log(
localStorage.getItem(key)
)
然后这两个页面是先后加载的,那么我们可以得出输出顺序是:
1 // 页面A
2 // 页面A
undefined // 页面B
console.log(3) // 页面A
因为请求是异步的,导致页面B那边拿不到 localStorage 里面的东西,而无法完成很多操作,导致了出现 BUG。所以得想想怎么去解决这个 BUG。
定时器
最简单的就是利用定时器去解决:
// 页面B
setTimeout(() => {
console.log(
localStorage.getItem(key)
)
})
但是这样是不对的,不好维护,滥用定时器会导致以后可能会有新的 BUG 出现!!!
发布订阅模式
所以还是使用发布订阅,首先实现一个发布订阅中心,以下是简单实现:
type Callback<T> = (data: T) => void;
class PubSub<T> {
private subscribers: Callback<T>[] = [];
subscribe(callback: Callback<T>): void {
this.subscribers.push(callback);
}
unsubscribe(callback: Callback<T>): void {
this.subscribers = this.subscribers.filter(fn => fn !== callback);
}
publish(data: T): void {
this.subscribers.forEach(fn => fn(data));
}
}
export const ps = new PubSub();
接着就可以用它来解决我们那个 BUG 了!!
// 页面A
console.log(1)
console.log(2)
http.get(url).then(res => {
console.log(3)
localStorage.setItem(key, res)
ps.publish(res)
})
// 页面B
// 订阅
ps.subscribe((res) => {
console.log(res)
console.log(
localStorage.getItem(key)
)
})
现在的输出顺序就是:
1 // 页面A
2 // 页面A
console.log(3) // 页面A
res // 页面B
res // 页面B
小结
这就是利用了 发布订阅模式 这种设计模式,来解决我们日常的一些简单业务,所以大家可以多用,这样在面试时就不怕面试官问你啦!