App下載

優(yōu)化性能與減少網(wǎng)絡(luò)流量:前端api請求緩存

夢夢貝莉雅 2023-12-04 10:18:00 瀏覽數(shù) (2025)
反饋

在開發(fā) web 應(yīng)用程序時,性能是一個重要的話題。為了提高用戶體驗和節(jié)省網(wǎng)絡(luò)資源,我們需要對一些頻繁或重復(fù)的 API 請求進行緩存,以減少不必要的服務(wù)器交互。緩存的原理是將第一次請求的數(shù)據(jù)保存在客戶端,之后再次請求時直接從緩存中獲取,而不是向服務(wù)器發(fā)送請求。

緩存的方式有很多種,根據(jù)不同的業(yè)務(wù)場景和需求,我們可以選擇合適的方案來實現(xiàn)緩存功能。本文將介紹前端 API 請求緩存的三種方案,從簡單到復(fù)雜,分別是:

一、數(shù)據(jù)緩存

  • 數(shù)據(jù)緩存是最簡單的一種緩存方案,它的思路是將第一次請求的數(shù)據(jù)保存在一個 Map 對象中,以 API 的名稱或參數(shù)作為鍵,以數(shù)據(jù)作為值。之后再次請求時,先從 Map 對象中查找是否有對應(yīng)的數(shù)據(jù),如果有則直接返回,如果沒有則向服務(wù)器發(fā)送請求,并將返回的數(shù)據(jù)保存在 Map 對象中。
  • 數(shù)據(jù)緩存的優(yōu)點是實現(xiàn)簡單,適用于一些不需要更新的靜態(tài)數(shù)據(jù)。缺點是無法處理同時多次請求的情況,也無法設(shè)置緩存的有效期,可能會導(dǎo)致數(shù)據(jù)過時或冗余。

示例代碼如下:

// 創(chuàng)建一個 Map 對象用于存儲數(shù)據(jù)
const dataCache = new Map();

// 定義一個獲取商品列表的 API
async function getWares() {
    // 以 API 的名稱作為鍵
    let key = "wares";
    // 從 Map 對象中獲取數(shù)據(jù)
    let data = dataCache.getkey;
    if (!data) {
        // 如果沒有數(shù)據(jù),向服務(wù)器發(fā)送請求
        const res = await request.get("/getWares");
        // 對返回的數(shù)據(jù)進行一些處理
        data = res.data;
        // 將數(shù)據(jù)保存在 Map 對象中
        dataCache.set(key, data);
    }
    // 返回數(shù)據(jù)
    return data;
}

調(diào)用方式如下:

// 第一次調(diào)用,向服務(wù)器發(fā)送請求,獲取數(shù)據(jù)
getWares().then((data) => {
    console.log(data);
});
// 第二次調(diào)用,從 Map 對象中獲取數(shù)據(jù),不再發(fā)送請求
getWares().then((data) => {
    console.log(data);
});

二、Promise 緩存

  • Promise 緩存是對數(shù)據(jù)緩存的改進,它的思路是將第一次請求的 Promise 對象保存在一個 Map 對象中,以 API 的名稱或參數(shù)作為鍵,以 Promise 對象作為值。之后再次請求時,先從 Map 對象中查找是否有對應(yīng)的 Promise 對象,如果有則直接返回,如果沒有則向服務(wù)器發(fā)送請求,并將返回的 Promise 對象保存在 Map 對象中。
  • Promise 緩存的優(yōu)點是可以處理同時多次請求的情況,避免重復(fù)發(fā)送請求,只有第一次請求會向服務(wù)器發(fā)送請求,之后的請求都會等待第一次請求的結(jié)果。缺點是無法設(shè)置緩存的有效期,可能會導(dǎo)致數(shù)據(jù)過時或冗余。

示例代碼如下:

// 創(chuàng)建一個 Map 對象用于存儲 Promise 對象
const promiseCache = new Map();

// 定義一個獲取商品列表的 API
function getWares() {
    // 以 API 的名稱作為鍵
    let key = "wares";
    // 從 Map 對象中獲取 Promise 對象
    let promise = promiseCache.getkey;
    // 如果沒有 Promise 對象
    if (!promise) {
        // 向服務(wù)器發(fā)送請求,并返回一個 Promise 對象
        promise = request.get("/getWares").then((res) => {
            // 對返回的數(shù)據(jù)進行一些處理
            return res.data;
        }).catch((error) => {
            // 如果請求出錯,從 Map 對象中刪除 Promise 對象,避免緩存錯誤的結(jié)果
            promiseCache.deletekey;
            // 拋出錯誤
            return Promise.reject(error);
        });
        // 將 Promise 對象保存在 Map 對象中
        promiseCache.set(key, promise);
    }
    // 返回 Promise 對象
    return promise;
}

調(diào)用方式如下:

// 第一次調(diào)用,向服務(wù)器發(fā)送請求,獲取數(shù)據(jù)
getWares().then((data) => {
    console.log(data);
});
// 第二次調(diào)用,從 Map 對象中獲取 Promise 對象,不再發(fā)送請求,等待第一次請求的結(jié)果
getWares().then((data) => {
    console.log(data);
});

三、多 Promise 緩存

  • 多 Promise 緩存是對 Promise 緩存的擴展,它的思路是將多個 API 請求的 Promise 對象保存在一個 Map 對象中,以 API 的名稱或參數(shù)作為鍵,以 Promise 對象作為值。之后再次請求時,先從 Map 對象中查找是否有對應(yīng)的 Promise 對象,如果有則直接返回,如果沒有則向服務(wù)器發(fā)送請求,并將返回的 Promise 對象保存在 Map 對象中。最后,使用 Promise.all 方法將多個 Promise 對象合并為一個 Promise 對象,統(tǒng)一返回結(jié)果。
  • 多 Promise 緩存的優(yōu)點是可以同時獲取多個 API 請求的數(shù)據(jù),提高效率,只有第一次請求會向服務(wù)器發(fā)送請求,之后的請求都會等待第一次請求的結(jié)果。缺點是無法設(shè)置緩存的有效期,可能會導(dǎo)致數(shù)據(jù)過時或冗余。另外,如果其中一個 API 請求出錯,會導(dǎo)致整個 Promise 對象被拒絕,無法獲取其他 API 請求的數(shù)據(jù)。

示例代碼如下:

// 定義一個對象,存儲 API 的名稱和對應(yīng)的請求地址
const querys = {
    wares: "/getWares",
    skus: "/getSku",
};

// 創(chuàng)建一個 Map 對象用于存儲 Promise 對象
const promiseCache = new Map();

// 定義一個函數(shù),用于同時獲取多個 API 請求的數(shù)據(jù)
async function queryAll(queryApiName) {
    // 判斷傳入的參數(shù)是否是數(shù)組
    const queryIsArray = Array.isArray(queryApiName);
    // 統(tǒng)一處理參數(shù),無論是字符串還是數(shù)組,都視為數(shù)組
    const apis = queryIsArray ? queryApiName : [queryApiName];
    // 創(chuàng)建一個數(shù)組,用于存儲所有的 Promise 對象
    const promiseApi = [];
    // 遍歷參數(shù)數(shù)組,對每個 API 進行處理
    apis.forEach((api) => {
        // 從 Map 對象中獲取 Promise 對象
        let promise = promiseCache.get(api);
        // 如果沒有 Promise 對象
        if (!promise) {
            // 向服務(wù)器發(fā)送請求,并返回一個 Promise 對象
            promise = request.get(querys[api]).then((res) => {
                // 對返回的數(shù)據(jù)進行一些處理
                return res.data;
            }).catch((error) => {
                // 如果請求出錯,從 Map 對象中刪除 Promise 對象,避免緩存錯誤的結(jié)果
                promiseCache.delete(api);
                // 拋出錯誤
                return Promise.reject(error);
            });
            // 將 Promise 對象保存在 Map 對象中
            promiseCache.set(api, promise);
        }
        // 將 Promise 對象添加到數(shù)組中
        promiseApi.push(promise);
    });
    // 使用 Promise.all 方法將多個 Promise 對象合并為一個 Promise 對象
    return Promise.all(promiseApi).then((res) => {
        // 根據(jù)傳入的參數(shù)是字符串還是數(shù)組來返回數(shù)據(jù),因為本身都是數(shù)組操作
        // 如果傳入的是字符串,則需要取出第一個元素
        return queryIsArray ? res : res[0];
    });
}

調(diào)用方式如下:

// 第一次調(diào)用,向服務(wù)器發(fā)送請求,獲取數(shù)據(jù)
queryAll("wares").then((data) => {
    console.log(data);
});
// 第二次調(diào)用,從 Map 對象中獲取 Promise 對象,不再發(fā)送請求,等待第一次請求的結(jié)果
queryAll(["wares", "skus"]).then((data) => {
    console.log(data);
});

總結(jié)

通過實施API請求緩存,我們可以顯著提高前端應(yīng)用程序的性能和用戶體驗。選擇合適的緩存方案取決于應(yīng)用程序的需求和特點。在實際開發(fā)中,我們可以根據(jù)數(shù)據(jù)的變化頻率、數(shù)據(jù)的重要性、存儲空間的限制等因素來選擇適當(dāng)?shù)姆桨?。結(jié)合合適的緩存方案,我們可以有效地減少網(wǎng)絡(luò)請求,提高應(yīng)用程序的響應(yīng)速度,并降低服務(wù)器負(fù)載。同時,需要注意緩存的更新策略,以確保數(shù)據(jù)的準(zhǔn)確性和實時性。

1698630578111788

如果你對前端工程師職業(yè)和編程技術(shù)感興趣,不妨訪問編程獅官網(wǎng)(http://m.hgci.cn/)。編程獅官網(wǎng)提供了大量的技術(shù)文章、編程教程和資源,涵蓋了前端工程師、編程、職業(yè)規(guī)劃等多個領(lǐng)域的知識。無論你是初學(xué)者還是有經(jīng)驗的開發(fā)者,編程獅官網(wǎng)都為你提供了有用的信息和資源,助你在編程領(lǐng)域取得成功。不要錯過這個寶貴的學(xué)習(xí)機會!

0 人點贊