成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

sendBeacon 刷新/關(guān)閉頁面之前發(fā)送請(qǐng)求

gxyz / 1937人閱讀

摘要:背景有一個(gè)任務(wù)非常耗時(shí)會(huì)消耗后臺(tái)大量算力,所以在退出頁面的時(shí)候,要求前端這邊發(fā)送一個(gè)請(qǐng)求來殺死任務(wù)。小結(jié)本文總共講了三個(gè),和,這個(gè)估計(jì)知道的人比較少,以后遇到前端埋點(diǎn)和頁面卸載前發(fā)送請(qǐng)求的需求,記得使用這三個(gè)。

背景:

有一個(gè)任務(wù)非常耗時(shí)會(huì)消耗后臺(tái)大量算力,所以在退出頁面的時(shí)候,要求前端這邊發(fā)送一個(gè)請(qǐng)求來殺死任務(wù)。

一開始以為這個(gè)需求非常簡單,就是在進(jìn)入其他路由前,發(fā)送一下請(qǐng)求,殺死一下任務(wù)就好了。

然而現(xiàn)實(shí)狠狠的打了我的臉,因?yàn)橥顺鲰撁娴膱鼍安恢骨袚Q路由~

退出頁面場景:

還在本網(wǎng)站,跳到其他路由

刷新頁面/關(guān)閉頁面也需要發(fā)送請(qǐng)求來殺死任務(wù)

還在本網(wǎng)站,跳到其他路由

這個(gè)比較簡單,在Vue中可以通過路由離開的鉤子beforeRouteLeave來實(shí)現(xiàn):

 beforeRouteLeave(to, from, next) {
    if (任務(wù)運(yùn)行中) {
        // 發(fā)送請(qǐng)求
    }else{
        next(true) // 用戶離開
    }
 }

刷新頁面/關(guān)閉頁面的情況:

然而在刷新頁面的時(shí)候,beforeRouteLeave并不會(huì)執(zhí)行,接著想到了下面這兩個(gè)API.

beforeunloadunload beforeunload 當(dāng)瀏覽器窗口關(guān)閉或者刷新時(shí)觸發(fā):

介紹

使用這個(gè)API可以阻止頁面直接關(guān)閉,用戶通過點(diǎn)擊確定/取消按鈕,來決定是否不關(guān)閉/刷新當(dāng)前頁面。

在 chrome 下長這個(gè)樣子,你們肯定都見過:

如何使用

這個(gè) API 的使用非常簡單,只要在頁面加載的時(shí)候監(jiān)聽一下此事件,在需要出現(xiàn)彈窗的時(shí)候return 一個(gè)可以轉(zhuǎn)化為 true 的值,就可以了。

// 頁面卸載之前
let killTask = false; // 是否殺死任務(wù)
window.onbeforeunload = e => {
  if (任務(wù)運(yùn)行 && 對(duì)應(yīng)頁面) {
    killTask = true;
    return "您可能有數(shù)據(jù)沒有保存"; // 在部分瀏覽器可以修改彈窗標(biāo)題
  } else {
    killTask = false;
  }
  // 沒有return一個(gè)可以轉(zhuǎn)化為true的值 就不會(huì)出現(xiàn)彈窗
};

出現(xiàn)此彈窗的瀏覽器行為

以下行為是基于 chorme:

焦點(diǎn):你沒有點(diǎn)擊取消/確定之前,焦點(diǎn)會(huì)一直在此彈窗上

你無法在出現(xiàn)彈窗的頁面上執(zhí)行任何操作

在其他頁面也只能執(zhí)行簡單的點(diǎn)擊操作,彈窗還是存在頁面中間,無法使用鍵盤,

鍵盤:鍵盤被綁定在彈窗上,只能通過按鍵Esc、Enter來執(zhí)行取消/確定操作

彈窗不是頁面的 dom,是瀏覽器的行為

用戶取消/確定,沒有回調(diào) API,無法得知

彈窗標(biāo)題

chrome 中刷新頁面的標(biāo)題:重新加載此網(wǎng)站?

chrome 中關(guān)閉頁面的標(biāo)題:離開此網(wǎng)站?

現(xiàn)在大部分瀏覽器都不允許修改彈窗的標(biāo)題,這個(gè)是為了安全考慮,來保證用戶不受到錯(cuò)誤信息的誤導(dǎo),

迷茫

一開始我以為既然可以攔截到用戶的刷新/關(guān)閉頁面的操作,出現(xiàn)了上面那個(gè)彈窗,這個(gè)需求就已經(jīng)做完了的時(shí)候。

然后發(fā)現(xiàn),瀏覽器竟然沒有提供用戶點(diǎn)擊確定/取消刷新頁面的回調(diào)。

到這里我陷入了迷茫,盯著beforeunload這個(gè) API 思考了起了人生的意義(其實(shí)是在發(fā)呆),盯著盯著,從beforeunloadbefore我也就想到了unload這個(gè) API。

瞬間又燃起了斗志,何不試試這個(gè)unload?

unload當(dāng)頁面正在被卸載的時(shí)候觸發(fā)該事件

介紹

當(dāng)頁面正在被卸載的時(shí)候觸發(fā)該事件,該事件不可取消,為不可逆操作。

使用

直接監(jiān)聽該事件就可以了。

window.onunload = e => {}

結(jié)合需求:

killTaskbeforeunload時(shí)定義的變量,每次進(jìn)入回調(diào),都會(huì)給killTask賦值,使用這個(gè)值就可以判斷什么時(shí)候可以發(fā)送請(qǐng)求殺死任務(wù)。

window.onunload = e => {
  if (killTask && 對(duì)應(yīng)頁面) {
    // 發(fā)送請(qǐng)求
  }
};

到這里大家肯定以為已經(jīng)做出來了該需求,事實(shí)上,并沒有!

無法發(fā)送異步請(qǐng)求

我使用的是axios來發(fā)送請(qǐng)求,請(qǐng)求發(fā)出去了,但是被取消了,服務(wù)器那邊根本沒有收到請(qǐng)求,如下。

經(jīng)過一頓分析:發(fā)現(xiàn)是axios請(qǐng)求是異步的問題,谷歌之后發(fā)現(xiàn)axios不支持同步的請(qǐng)求

最后使用原生的XMLHttpRequest對(duì)象,讓請(qǐng)求同步

大功告成! 實(shí)際上,上面才是我第一次要發(fā)的內(nèi)容,而下面更好的解決方法!

缺陷與更好的建議:

當(dāng)我把這篇文章發(fā)布在公眾號(hào)上,被奇舞周刊轉(zhuǎn)載了,上面一些大佬給我提了一些建議。

研究了一下,結(jié)果...好吧!我承認(rèn)我是菜雞。

hey~ 不過這正是我寫博客的收獲之一,分享經(jīng)驗(yàn),收獲知識(shí)!

性能缺陷:

XHR同步請(qǐng)求會(huì)阻礙頁面卸載,如果是刷新/跳轉(zhuǎn)頁面的話,頁面重新展示速度會(huì)變慢,導(dǎo)致性能問題。

畢竟向網(wǎng)絡(luò)發(fā)送請(qǐng)求并獲得響應(yīng)可能會(huì)超級(jí)慢,有可能是用戶網(wǎng)絡(luò)環(huán)境比較差,又或者是服務(wù)器掛了,請(qǐng)求一直沒返回回來...

基于性能問題,大佬們推薦使用Beacon代替XHR,然后經(jīng)過一番搜索...

Beacon API

Beacon API用于將少量數(shù)據(jù)通過post請(qǐng)求發(fā)送到服務(wù)器。

Beacon是非阻塞請(qǐng)求,不需要響應(yīng)

完美解決性能缺陷問題:

瀏覽器將 Beacon 請(qǐng)求排隊(duì)讓它在空閑的時(shí)候執(zhí)行并立即返回控制

它在unload狀態(tài)下也可以異步發(fā)送,不阻塞頁面刷新/跳轉(zhuǎn)等操作。

所以Beacon可以完美解決上面提到的因XHR同步請(qǐng)求阻塞而引起的性能缺陷問題。

使用:navigator.sendBeacon()

完整API

let result = navigator.sendBeacon(url, data);

Beacon是掛在navigator下面的,上面就是它的完整API。

result是一個(gè)布爾值,代表這次發(fā)送請(qǐng)求的結(jié)果:

如果瀏覽器接受并且把請(qǐng)求排隊(duì)了則返回 tru

如果在這個(gè)過程中出現(xiàn)了問題就返回 false

navigator.sendBeacon接受兩個(gè)參數(shù):

url: 請(qǐng)求的 URL。請(qǐng)求是 POST 請(qǐng)求。

data: 要發(fā)送的數(shù)據(jù)。 數(shù)據(jù)類型可以是:ArrayBufferView, Blob, FormData,Sting。

來看一個(gè)用FormData來傳遞數(shù)據(jù)的栗子,你就懂了:

// 創(chuàng)建一個(gè)新的 FormData 并添加一個(gè)鍵值對(duì)
let data = new FormData();
data.append("hello", "world");
let result = navigator.sendBeacon("./src", data);
if (result) { 
  console.log("請(qǐng)求成功排隊(duì) 等待執(zhí)行");
} else {
  console.log("失敗");
}
瀏覽器支持:

瀏覽器支持:Edge:14+,F(xiàn)irefox:31+,Chrome:39+,Opera:26+,IE:不支持。

雖然現(xiàn)在瀏覽器對(duì)sendBeacon的支持很好,我們對(duì)其做一下兼容性處理也是有必要的:

if (navigator.sendBeacon) {
  // Beacon 代碼
} else {
 // 回退到 XHR同步請(qǐng)求或者不做處理
}
web wroker中使用Beacon

因?yàn)?b>Beacon是掛在navigator 下面,而web worker也有navigator ,去找了一下,真的給我找到了。

這兒有一個(gè)MDN提供的栗子),可以點(diǎn)進(jìn)去看一下。

PS:對(duì)web worker不熟悉的同學(xué)可以看我這篇文章

Beacon其他相關(guān)

客戶端優(yōu)化:可以將 Beacon 請(qǐng)求合并到其他請(qǐng)求上,一同處理, 尤其在移動(dòng)環(huán)境下。

Beacon更多的情況是用于做前端埋點(diǎn),監(jiān)控用戶活動(dòng),它的初衷也基于此。

小結(jié)

本文總共講了三個(gè)API,beforeunload、unloadBeaconBeacon這個(gè)API估計(jì)知道的人比較少,以后遇到前端埋點(diǎn)和頁面卸載前發(fā)送請(qǐng)求的需求,記得使用這三個(gè)API。

以上2019.02.19

博客、前端積累文檔、公眾號(hào)、GitHub

參考資料:

MDN

頁面跳轉(zhuǎn)時(shí),統(tǒng)計(jì)數(shù)據(jù)丟失問題探討

使用 Web Beacon API 記錄活動(dòng)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/102061.html

相關(guān)文章

  • 在單頁應(yīng)用中,如何優(yōu)雅的上報(bào)前端性能數(shù)據(jù)

    摘要:本文的介紹的是如何設(shè)計(jì)一個(gè)通用的可以以較小的侵入性,自動(dòng)上報(bào)前端的性能數(shù)據(jù)。具體的做法可以看我的上一篇文章在單頁應(yīng)用中,如何優(yōu)雅的監(jiān)聽的變化。三如何上報(bào)性能數(shù)據(jù)那么如何上報(bào)性能數(shù)據(jù)呢,我們第一反應(yīng)就是通過請(qǐng)求的形式來上報(bào)前端性能數(shù)據(jù)。 ??最近在做一個(gè)較為通用的前端性能監(jiān)控平臺(tái),區(qū)別于前端異常監(jiān)控,前端的性能監(jiān)控主要需要上報(bào)和展示的是前端的性能數(shù)據(jù),包括首頁渲染時(shí)間、每個(gè)頁面的白屏?xí)r...

    KitorinZero 評(píng)論0 收藏0
  • 在單頁應(yīng)用中,如何優(yōu)雅的上報(bào)前端性能數(shù)據(jù)

    摘要:本文的介紹的是如何設(shè)計(jì)一個(gè)通用的可以以較小的侵入性,自動(dòng)上報(bào)前端的性能數(shù)據(jù)。具體的做法可以看我的上一篇文章在單頁應(yīng)用中,如何優(yōu)雅的監(jiān)聽的變化。三如何上報(bào)性能數(shù)據(jù)那么如何上報(bào)性能數(shù)據(jù)呢,我們第一反應(yīng)就是通過請(qǐng)求的形式來上報(bào)前端性能數(shù)據(jù)。 ??最近在做一個(gè)較為通用的前端性能監(jiān)控平臺(tái),區(qū)別于前端異常監(jiān)控,前端的性能監(jiān)控主要需要上報(bào)和展示的是前端的性能數(shù)據(jù),包括首頁渲染時(shí)間、每個(gè)頁面的白屏?xí)r...

    curried 評(píng)論0 收藏0
  • 在單頁應(yīng)用中,如何優(yōu)雅的上報(bào)前端性能數(shù)據(jù)

    摘要:本文的介紹的是如何設(shè)計(jì)一個(gè)通用的可以以較小的侵入性,自動(dòng)上報(bào)前端的性能數(shù)據(jù)。具體的做法可以看我的上一篇文章在單頁應(yīng)用中,如何優(yōu)雅的監(jiān)聽的變化。三如何上報(bào)性能數(shù)據(jù)那么如何上報(bào)性能數(shù)據(jù)呢,我們第一反應(yīng)就是通過請(qǐng)求的形式來上報(bào)前端性能數(shù)據(jù)。 ??最近在做一個(gè)較為通用的前端性能監(jiān)控平臺(tái),區(qū)別于前端異常監(jiān)控,前端的性能監(jiān)控主要需要上報(bào)和展示的是前端的性能數(shù)據(jù),包括首頁渲染時(shí)間、每個(gè)頁面的白屏?xí)r...

    beanlam 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<