亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

service worker輕度探索 - 解決運(yùn)營(yíng)活動(dòng)需求中的圖片加載問(wèn)題?

amc / 3234人閱讀

摘要:寫在前面本文首發(fā)于公眾號(hào)符合預(yù)期的做過(guò)運(yùn)營(yíng)活動(dòng)需求的同學(xué)都知道,一般一個(gè)運(yùn)營(yíng)活動(dòng)中會(huì)用到很多的圖片資源。注意事項(xiàng)注冊(cè)完后,我們就劫持了頁(yè)面的所有請(qǐng)求。

寫在前面
本文首發(fā)于公眾號(hào):符合預(yù)期的CoyPan

做過(guò)運(yùn)營(yíng)活動(dòng)需求的同學(xué)都知道,一般一個(gè)運(yùn)營(yíng)活動(dòng)中會(huì)用到很多的圖片資源。用戶訪問(wèn)首頁(yè)時(shí),都會(huì)看到一個(gè)loading態(tài),表示頁(yè)面正在加載所需的所有圖片資源。像下面這樣:

手動(dòng)加載一個(gè)圖片的代碼也很簡(jiǎn)單:

var img = new Image();
img.onload = function(){ ... }
img.src = "圖片地址";

之所以要提前加載所有的圖片,是為了在后續(xù)的頁(yè)面中使用圖片時(shí),不會(huì)因?yàn)樾枰虞d圖片而產(chǎn)生耗時(shí),導(dǎo)致體驗(yàn)問(wèn)題。本文所要討論的場(chǎng)景就是:怎么樣做到在首頁(yè)加載圖片后,直接在后面的業(yè)務(wù)邏輯中直接使用提前加載好的圖片呢?答案就是:把圖片存下來(lái)。

緩存首頁(yè)加載的圖片

我能想到的這種場(chǎng)景下的緩存圖片方法有兩種:

使用瀏覽器的緩存。圖片在第一次請(qǐng)求成功后,一般都會(huì)設(shè)置緩存。在頁(yè)面后續(xù)的業(yè)務(wù)邏輯中,如果說(shuō)想使用某圖片,直接正常發(fā)起圖片請(qǐng)求即可,瀏覽器會(huì)走緩存,甚至是從內(nèi)存中直接返回這個(gè)圖片。

將加載好的Image對(duì)象直接保存在內(nèi)存中。這種方法很適用canvas中畫圖的場(chǎng)景,直接把保存下來(lái)的Image對(duì)象扔到canvas的drawImage中即可。

做業(yè)務(wù)需要不斷的總結(jié),思考。還能用什么方法來(lái)實(shí)現(xiàn)圖片的緩存呢 ? 我嘗試了一下Service Worker,本文將介紹一下Service Worker在這種業(yè)務(wù)場(chǎng)景下的應(yīng)用。

本文只是輕輕嘗試了一下Service Worker,并未在線上項(xiàng)目中應(yīng)用。
Service Worker

Service Worker是PWA的重要組成部分,其包含安裝、激活、等待、銷毀等四個(gè)生命周期。主要有以下的特性:

一個(gè)獨(dú)立的 worker 線程,獨(dú)立于當(dāng)前網(wǎng)頁(yè)進(jìn)程,有自己獨(dú)立的 worker context。

一旦被 install,就永遠(yuǎn)存在,除非被手動(dòng) unregister

用到的時(shí)候可以直接喚醒,不用的時(shí)候自動(dòng)睡眠

可編程攔截代理請(qǐng)求和返回,緩存文件,緩存的文件可以被網(wǎng)頁(yè)進(jìn)程取到(包括網(wǎng)絡(luò)離線狀態(tài))

離線內(nèi)容開(kāi)發(fā)者可控

能向客戶端推送消息

不能直接操作 DOM

必須在 HTTPS 環(huán)境下才能工作( 或 http://localhost )

異步實(shí)現(xiàn),內(nèi)部大都是通過(guò) Promise 實(shí)現(xiàn)

在本文所描述的業(yè)務(wù)場(chǎng)景中,主要是應(yīng)用service worker的攔截代理請(qǐng)求和返回的功能。

關(guān)于service worker的基礎(chǔ),谷歌開(kāi)發(fā)者網(wǎng)站上有詳細(xì)的介紹,這里就不贅述了。

地址在這里:https://developers.google.com...

需要注意的是,service worker一定要謹(jǐn)慎使用,因?yàn)樗匾?,一旦注?cè),站點(diǎn)的所有請(qǐng)求都會(huì)被控制。

Service Worker的示例

結(jié)合文章開(kāi)頭所描述的場(chǎng)景,我們先來(lái)寫一些必要的業(yè)務(wù)函數(shù)。

// 加載一個(gè)圖片
function loadImage(imgUrl) {
    return new Promise((resolve, reject)=>{
        const img = new Image();
        img.onload = function() {
            resolve();
        };
        img.src = imgUrl;
    });
}

// 加載一堆圖片
function loadImageList(imgList) {
    return Promise.all(imgList.map(function (imgUrl) {
        return loadImage(imgUrl);
    }));
}

下面是service worker的代碼:

self.addEventListener("install", function (event) {
    console.log("install");
});

self.addEventListener("fetch", function (evt) {
    evt.respondWith(
        caches.match(evt.request).then(function(response) {
            if (response) {
                return response;
            }
            const request = evt.request.clone();
            return fetch(request).then(function (response) {
                if (!response || response.status !== 200 || !response.headers.get("Content-type").match(/image/)) {
                    return response;
                }
                const responseClone = response.clone(); // 流數(shù)據(jù)需要克隆一份。注意事項(xiàng)②
                caches.open("test-cache").then(function (cache) { 
                    cache.put(evt.request, responseClone);
                });
                return response;
            });
        })
    )
});

self.addEventListener("activate", function () {
    console.log("activate");
    clients.claim(); // 首次activate后,就控制頁(yè)面。注意事項(xiàng)①
});

注冊(cè)完service worker后,我們就劫持了頁(yè)面的所有請(qǐng)求。每一次請(qǐng)求經(jīng)過(guò)service worker時(shí),都會(huì)判斷剛請(qǐng)求是否已有緩存,如果有緩存,就直接返回結(jié)果。沒(méi)有緩存時(shí),才會(huì)向服務(wù)器發(fā)起請(qǐng)求,并且將圖片請(qǐng)求的結(jié)果緩存起來(lái)。

在業(yè)務(wù)代碼中,我們注冊(cè)并使用這個(gè)service worker的代碼如下:

// 需要加載的圖片列表
const imgArr = ["http://xxx.jpg", "..."];

// 注冊(cè)service worker
function registerServiceWorker() {
    if ("serviceWorker" in navigator) {
        return navigator.serviceWorker.register("http://localhost:8080/service.js");
    } else {
        // 沒(méi)有service的處理邏輯省略
    }
}

registerServiceWorker().then(registration => { // 注意事項(xiàng)③
    let serviceWorker;
    if (registration.installing) {
        console.log("registration.installing");
        serviceWorker = registration.installing;
    } else if (registration.waiting) {
        console.log("registration.waiting");
        serviceWorker = registration.waiting;
    } else if (registration.active) {
        console.log("registration.active");
        serviceWorker = registration.active;
        loadImageList(imgArr);
    }
    if (serviceWorker) {
        serviceWorker.addEventListener("statechange", function (e) {
            if(e.target.state === "activated") {
                // 首次注冊(cè)時(shí)
                console.log("首次注冊(cè)sw時(shí),sw激活");
                loadImageList(imgArr);
            }
        });
    }
}).catch(e => {
    console.log(e);
});

注意事項(xiàng):

正常情況下,service worker剛注冊(cè)時(shí),是不會(huì)控制頁(yè)面的,即無(wú)法攔截到頁(yè)面的請(qǐng)求。需要用戶刷新頁(yè)面,再次訪問(wèn)時(shí),service worker才會(huì)攔截頁(yè)面請(qǐng)求。這與我們的需求場(chǎng)景不符合。我們的需求是:用戶首次訪問(wèn)請(qǐng)求圖片資源時(shí),就需要對(duì)返回的圖片進(jìn)行緩存。所以,需要在service worker進(jìn)入activate狀態(tài)后,通過(guò)clients.claim()來(lái)獲得頁(yè)面的控制權(quán)。不過(guò),這種方式并不被提倡

service worker攔截到請(qǐng)求后,我們需要拷貝返回的數(shù)據(jù)流,才能存入緩存。

在業(yè)務(wù)代碼中,我們每次都需要調(diào)用navigator.serviceWorker.register來(lái)拿到一個(gè)service worker。瀏覽器會(huì)判斷當(dāng)前service worker的狀態(tài),返回對(duì)應(yīng)的對(duì)象。我們需要保證在service worker準(zhǔn)備無(wú)誤后,再發(fā)起圖片的請(qǐng)求。由于server worker的自身邏輯需要一定的時(shí)間,所以我們發(fā)起圖片請(qǐng)求的時(shí)間會(huì)被延后。

使用service worker后的效果

以我做的運(yùn)營(yíng)活動(dòng)項(xiàng)目為例,使用service worker之前,網(wǎng)絡(luò)請(qǐng)求是這樣的:

活動(dòng)頁(yè)首頁(yè),首次集中請(qǐng)求圖片

活動(dòng)頁(yè)后續(xù)頁(yè)面中,使用加載好的圖片:

使用service-worker之后,網(wǎng)絡(luò)請(qǐng)求是這樣的:

活動(dòng)頁(yè)首頁(yè),首次集中請(qǐng)求圖片:

活動(dòng)頁(yè)后續(xù)頁(yè)面中,使用加載好的圖片:

可以看到,我們成功使用service worker劫持了頁(yè)面的請(qǐng)求,并且將圖片緩存到了瀏覽器的cache storage中。我們來(lái)看一下瀏覽器的緩存。這里的緩存都是http response。

另外這里多說(shuō)一句,可以使用下面的代碼,來(lái)查看當(dāng)前網(wǎng)站可以使用的瀏覽器本地存儲(chǔ)空間

if ("storage" in navigator && "estimate" in navigator.storage) {
  navigator.storage.estimate().then(({usage, quota}) => {
    console.log(`Using ${usage} out of ${quota} bytes.`);
  });
}
一些思考

在本文提到的場(chǎng)景中,我們?cè)谟脩羰状卧L問(wèn)頁(yè)面時(shí),先注冊(cè)了service worker,并且使service worker立即控制頁(yè)面,然后再開(kāi)始請(qǐng)求圖片。這種做法延后了圖片請(qǐng)求的發(fā)起時(shí)間,并且從上面的圖中可以看到,通過(guò)service worker加載圖片的耗時(shí)比正常直接請(qǐng)求圖片耗時(shí)略長(zhǎng)。這些因素導(dǎo)致首屏?xí)r間被延后了。另外,作為運(yùn)營(yíng)活動(dòng)頁(yè),同一個(gè)用戶也不會(huì)在幾天內(nèi)多次訪問(wèn),因此service worker的【繞過(guò)網(wǎng)絡(luò),立即響應(yīng)請(qǐng)求】的特性并不能很好地發(fā)揮出來(lái)。因此,在本文描述的場(chǎng)景中,使用service worker來(lái)做緩存并不是最佳實(shí)踐。

關(guān)于service worker做緩存的最佳實(shí)踐以及使用場(chǎng)景,可以查看這篇文章:

https://developers.google.com...

service worker最適合的場(chǎng)景還是資源離線化,用戶二次進(jìn)入頁(yè)面時(shí)可以達(dá)到資源秒加載,不會(huì)受網(wǎng)絡(luò)狀況的影響。

寫在后面

本文從業(yè)務(wù)的角度出發(fā),輕度探索了service worker在文章開(kāi)頭給出的業(yè)務(wù)場(chǎng)景中的應(yīng)用。后續(xù)會(huì)考慮在合適的業(yè)務(wù)場(chǎng)景中進(jìn)行應(yīng)用。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/102329.html

相關(guān)文章

  • 使用service worker做緩存來(lái)加快首屏速度,可行么?

    摘要:目標(biāo)是探索是否能夠加快頁(yè)面首屏速度。實(shí)驗(yàn)組瀏覽器支持,本次時(shí),進(jìn)行初始化。從上面的直觀對(duì)比可以看出,個(gè)指標(biāo),組的分位值都略微大于組的分位值,差距在幾十毫秒左右。最終,我也沒(méi)有采用來(lái)優(yōu)化首屏速度。 寫在前面 本文首發(fā)于公眾號(hào):符合預(yù)期的CoyPan 不久之前,我簡(jiǎn)單探索了service worker在一個(gè)活動(dòng)運(yùn)營(yíng)頁(yè)面中的應(yīng)用,可以參考我之前的這篇文章: service worker輕度探...

    tinysun1234 評(píng)論0 收藏0
  • 前端應(yīng)該知曉的PWA

    摘要:對(duì)來(lái)說(shuō)主要兩個(gè)事件。是當(dāng)前的變量,執(zhí)行該方法表示強(qiáng)制當(dāng)前處在狀態(tài)的進(jìn)入狀態(tài)。頁(yè)面關(guān)閉之后,老的會(huì)被干掉,新的接管頁(yè)面新的生效后會(huì)觸發(fā)事件。 一、傳統(tǒng)web 應(yīng)用 當(dāng)前web應(yīng)用在移動(dòng)時(shí)代并沒(méi)有達(dá)到其在桌面設(shè)備上流行的程度,下面有張圖來(lái)對(duì)比與原生應(yīng)用之間的差別。 showImg(https://segmentfault.com/img/bVbaD44?w=1920&h=1080)...

    GT 評(píng)論0 收藏0
  • serverless在微店node領(lǐng)域的探索應(yīng)用

    摘要:參與者流量來(lái)自于內(nèi)部系統(tǒng)和外部流量,其中大部分來(lái)自于外部流量。水平擴(kuò)容服務(wù)的水平擴(kuò)容重要性不言而喻。 背景 目前微店中臺(tái)團(tuán)隊(duì)為了滿足公司大部分產(chǎn)品、運(yùn)營(yíng)以及部分后端開(kāi)發(fā)人員的嘗鮮和試錯(cuò)的需求,提供了一套基于圖形化搭建的服務(wù)端接口交付方案,利用該方案及提供的系統(tǒng)可生成一副包含運(yùn)行時(shí)環(huán)境定義可立即運(yùn)行的工程代碼,最后,通過(guò) 某種serverless平臺(tái) 實(shí)現(xiàn)生成后代碼的部署、CI、運(yùn)行、反...

    mikyou 評(píng)論0 收藏0
  • JavaScript是如何工作的:Web推送通知的機(jī)制

    摘要:在端,盡管開(kāi)發(fā)人員對(duì)其功能的需求很高,但出于某些原因,推送通知被引入的時(shí)間比較晚。發(fā)送推送通知在服務(wù)器上實(shí)現(xiàn)調(diào)用,該調(diào)用觸發(fā)到用戶設(shè)備的推送消息。推送服務(wù)推送服務(wù)是接收請(qǐng)求驗(yàn)證請(qǐng)求并將推送消息發(fā)送到對(duì)應(yīng)的瀏覽器。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第9篇。 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇優(yōu)質(zhì)文章等著你! 如果你錯(cuò)過(guò)了前面的章節(jié),可以在...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<