有时候,我们的代码更新后,需要在测试环境通知用户,手动刷新页面,以获得最新的交互体验,该怎么做呢?话不多说,直接show me code!
// updater.ts
interface Options {
timer?: number
}
export class Updater {
//存储第一次值也就是script 的hash 信息
oldScript: string[]
//获取新的值 也就是新的script 的hash信息
newScript: string[]
//小型发布订阅通知用户更新了
dispatch: Record<string, any[]>
constructor(options: Options) {
this.oldScript = [];
this.newScript = []
this.dispatch = {}
this.init() //初始化
this.timing(options?.timer)//轮询
}
async init() {
const html: string = await this.getHtml()
this.oldScript = this.parserScript(html)
}
async getHtml() {
const html = await fetch("/").then(res => res.text()).catch(e => console.log(e));//读取index html
return html || ""
}
parserScript(html: string) {
const reg = new RegExp(/<script(?:\s+[^>]*)?>(.*?)<\/script\s*>/ig) //script正则
return html.match(reg) as string[] //匹配script标签
}
//发布订阅通知
on(key: "no-update" | "update", fn: any) {
(this.dispatch[key] || (this.dispatch[key] = [])).push(fn)
return this;
}
compare(oldArr: string[], newArr: string[]) {
const base = oldArr.length
const arr = Array.from(new Set(oldArr.concat(newArr)))
//如果新旧length 一样无更新
if (arr.length === base) {
console.info("系统无更新")
this.dispatch["no-update"]?.forEach(fn => {
fn()
})
} else {
//否则通知更新
this.dispatch["update"].forEach(fn => {
fn()
})
}
}
timing(time = 10000) {
//轮询
setInterval(async () => {
const newHtml = await this.getHtml()
this.newScript = this.parserScript(newHtml)
this.compare(this.oldScript, this.newScript)
}, time)
}
}
使用示例:
import { Updater } from "utils/updater";
const App = () => {
useEffect(() => {
// 检测是否网站有发布更新,避免页面Error
const up = new Updater({ timer: 500000 })
up.on("update", () => {
Modal.destroyAll()
Modal.confirm({
title: "提示",
centered: true,
content: "网页功能已更新,需要刷新页面,是否刷新页面?",
onOk: () => {
window.location.reload()
}
})
})
},[])
return (<div>....</div>)
}