Redistribución de la implementación de front-end pura de js para notificar a los usuarios que actualicen la página web

Demanda: a veces, después de conectarse, el usuario aún permanece en la página anterior. El usuario no sabe que la página web se ha vuelto a implementar. Al saltar a la página, a veces el hash de conexión js ha cambiado, lo que provoca un error y el usuario no puede experimentar La nueva función debe optimizarse. Cada vez que los clientes ingresen al sistema después del empaquetado y lanzamiento, se les pedirá que actualicen el sistema y avisarán a los clientes.

Solución: cargue un archivo json al público y luego cambie el json cada vez que se empaquete. La primera vez obtuve los datos de ison y los guardé, y luego sondeé la solicitud hasta que cambió el tiempo en los datos de json y pregunté el usuario.

El front-end determina en función del valor hash del script src generado después del empaquetado. Cada paquete generará un valor hash único. Siempre que se sondee para determinar si es diferente, debe haberse vuelto a implementar.
Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí
Implementación de código: personalice un archivo js o ts
RedeployMessage.ts
y copie y pegue el siguiente código en él

interface Options {
timer?: number
}

export class Updater {
    oldScript: string[] //存储第一次值也就是script 的hash 信息
    newScript: string[] //获取新的值 也就是新的script 的hash信息
    dispatch: Record<string, Function[]> //小型发布订阅通知用户更新了
    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());//读取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: Function) {
        (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) {
            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)
    }
}

¿Y que? —Haga referencia a este archivo ts en el archivo de aplicación más externo.

Si es un proyecto vue, colóquelo en la función de enlace onMoutend

//实例化该类
const up = new Updater({
    timer:2000
})
//未更新通知
up.on('no-update',()=>{
   console.log('未更新')
})
//更新通知
up.on('update',()=>{
    console.log('更新了')
}) 

Insertar descripción de la imagen aquí


Si es un proyecto de reacción, se puede colocar en componenteDidMount()

//实例化该类
const up = new Updater({
    timer:2000
})
//未更新通知
up.on('no-update',()=>{
   console.log('未更新')
})
//更新通知
up.on('update',()=>{
    console.log('更新了'),更新进行提示弹框消息。自己封装就好了,一般都有组件直接用
}) 

Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

Preste atención al posible problema, es decir, se le solicita actualizar pero el cliente nunca hace clic para actualizar, y luego la página enviará un mensaje emergente después de un temporizador, en este momento debemos recordar borrar el temporizador clearInterval ().
Es decir, asignar una variable al sondear.

 timing(time = 10000) {
     //轮询
  let clearTime =   setInterval(async () => {
        const newHtml = await this.getHtml()
        this.newScript = this.parserScript(newHtml)
        this.compare(this.oldScript, this.newScript)
    }, time)
}

然后再调用定时器的地方,清除,即 
//否则通知更新
        this.dispatch['update'].forEach(fn => {
            fn()
            clearInterval(this.clearTime)
        })

Hay otra solución: puedes leer lo que escribió este blogger e ingresar . No lo intenté. bienvenido a burlarse

Supongo que te gusta

Origin blog.csdn.net/lzfengquan/article/details/131451542
Recomendado
Clasificación