亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript使用promise處理多重復請求

 更新時間:2021年05月26日 09:28:07   作者:專業(yè)逮蝦戶aaa  
處理重復請求的文章想必大家也看過了很多,大多數(shù)都是分為在response返回之前發(fā)現(xiàn)重復請求就return掉的和使用節(jié)流/防抖來間接規(guī)避用戶頻繁操作兩種版本的。本文主要介紹了JavaScript使用promise處理多重復請求,感興趣的可以了解一下

一、為什么要寫這個文章?

處理重復請求的文章想必大家也看過了很多,大多數(shù)都是分為在response返回之前發(fā)現(xiàn)重復請求就return掉的和使用節(jié)流/防抖來間接規(guī)避用戶頻繁操作兩種版本的。最近在使用的過程的中,發(fā)現(xiàn)這兩個版本在某些場景下還是有些局限性。

二、問題場景

如圖,我這個h5的頁面,頂部和底部都要顯示這個名片組件。這些名片的信息是通過一個接口來獲取的,當這個組件在當前頁面被初始化時,就會發(fā)生兩次重復的請求。

這時會面臨幾個抉擇:

1. 不對重復請求做任何處理。

  • 缺點1:造成不必要的資源浪費,增大服務器的壓力
  • 缺點2:http請求在瀏覽器中是有并發(fā)數(shù)限制的,如果頁面首屏的請求較多且沒有分層級加載的話,很容易造成請求阻塞,影響用戶第一時間看到主要內容

2. 對重復請求直接return掉。這也是部分文章的做法,不過這種做法有種局限性,就是直接認定后面的重復請求均為無效請求。

  • 無效請求場景:用戶點擊了某個按鈕進行查詢或保存,在請求結果返回之前,后面點擊基本都算是無效請求,這種請求就是應該被阻止的。當然,也可以通過在按鈕上添加節(jié)流/防抖來規(guī)避這個問題
  • 為何不適用于目前場景:這兩個名片的組件都是需要數(shù)據來渲染的,如果第二次重復的請求被return了,其中一個組件的名片就會沒有數(shù)據。

3. 把請求從組件中抽離出來放到父級的業(yè)務頁面中,再以props的方式傳進組件。

  • 好處:只需要請求一次,兩個組件就可以共享一份數(shù)據。
  • 局限性:只適用于單個業(yè)務頁面用到的情況。事實上這個組件很多個業(yè)務頁面在用,即使把請求的函數(shù)抽成公用的api,也是要在每個業(yè)務頁面初始化的時候調用一次,然后再以props的方式傳進組件。

三、解決方式

核心思想

  • 初始化一個handleList的數(shù)組
  • 在請求發(fā)送前,根據入參是否相同判斷是否為重復請求
    • 非重復請求:把改請求的參數(shù)和請求返回的Promise添加至數(shù)組中
    • 重復請求:使用find查找直接返回對應的Promise
  • 請求完成后把handleList中之前添加的請求信息移除。

這個方案是什么都可以使用的,無論是使用axios、jq、fetch、小程序request。這里就寫實現(xiàn)的原理,使用時直接把對應的代碼放到對應的請求時機即可。

代碼示例

let handleList = [] // 請求列表
/**
 * 模擬請求
 * @author waldon
 * @date 2020/6/9
 */
const httpRequest = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`請求成功,時間戳為:${new Date().getTime()}`)
    }, 1000)
  })
}
/**
 * 請求的相關處理
 * @author waldon
 * @date 2020/6/9
 * @param {String} url -
 * @param {Object} requestObj - 請求參數(shù)
 * @returns {Promise} - 請求的promise
 */
function requestTest(url, requestObj = {}) {
  // 因為入參一般不會涉及到復雜類型,JSON.stringify進行序列化對比其實夠用了
  // 有個局限性就是入參的順序改變了就會影響判斷,不過這種特殊的改變一般在重復請求中不會出現(xiàn)
  // 實在是有這種需求的,換成其他遞歸對比的api,lodash也有類似的api
  const sameHandle = handleList.find(
    (item) => item.url === url && JSON.stringify(item.requestObj) === JSON.stringify(requestObj)
  )
  if (sameHandle) {
    // 遇到相同請求直接返回之前請求的promise
    console.log(`存在重復請求,直接返回`)
    return sameHandle.handle
  }
  const handle = new Promise((resolve, reject) => {
    httpRequest()
      .then((res) => {
        resolve(res)
      })
      .catch((err) => {
        reject(err)
      })
      .finally(() => {
        // 無論請求結果如果,都需要把對應的請求移除掉
        handleList = handleList.filter(
              (item) =>
                item.url !== url && JSON.stringify(item.requestObj) !== JSON.stringify(requestObj)
            )
      })
  })
  handleList.push({ url, requestObj, handle })
  return handle
}

// *******************************我是華麗的分割線 開始使用*******************************
const params = {
  name: 'waldon'
}
requestTest('/ajax/sameUrl', params).then((res) => {
  console.log(`首次請求結果`, res)
  console.log(`handleList:`, handleList)
})
requestTest('/ajax/sameUrl', params).then((res) => {
  console.log(`重復請求結果`, res)
  console.log(`handleList:`, handleList) // 請求列表中始終只有一個請求
  setTimeout(() => {
    console.log(`請求完成后的handleList:`, handleList) // 請求完成handleList對應的請求會被清除
  }, 100)
})
setTimeout(() => {
  // 特意延遲500ms請求,因為我們設置了接口1s才返回,所以應該得到一樣的結果
  requestTest('/ajax/sameUrl', params).then((res) => {
    console.log(`重復請求結果`, res)
    console.log(`handleList:`, handleList)
  })
}, 500)

輸出結果

存在重復請求,直接返回
存在重復請求,直接返回
首次請求結果 請求成功,時間戳為:1621650375540
handleList: [
  {
    url: '/ajax/sameUrl',
    requestObj: { name: 'waldon' },
    handle: Promise { '請求成功,時間戳為:1621650375540' }
  }
]
重復請求結果 請求成功,時間戳為:1621650375540
handleList: [
  {
    url: '/ajax/sameUrl',
    requestObj: { name: 'waldon' },
    handle: Promise { '請求成功,時間戳為:1621650375540' }
  }
]
重復請求結果 請求成功,時間戳為:1621650375540
handleList: [
  {
    url: '/ajax/sameUrl',
    requestObj: { name: 'waldon' },
    handle: Promise { '請求成功,時間戳為:1621650375540' }
  }
]
請求完成后的handleList: []

代碼地址 codepen

https://codepen.io/waldonUB/pen/ZEeeONM

注意的點

  • 不要對response中的數(shù)據進行增刪操作。因為重復請求返回Promise中的對象引用地址都是同一個,改動了就會造成數(shù)據污染。特殊情況時可以淺拷貝響應結果再處理,或者是增加對應的斷言。
  • 處理重復的請求時,最好在log中提示一下,同時在組件中注釋好原因和使用場景,避免他人誤改
  • 做好極端情況下,請求失敗的處理,設置有效時間置空和移除請求信息,避免因為閉包堆積過多無用的請求信息造成內存泄漏。

到此這篇關于JavaScript使用promise處理多重復請求的文章就介紹到這了,更多相關js promise多重復請求內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

  • 淺析javascript中的事件代理

    淺析javascript中的事件代理

    這篇文章主要介紹了淺析javascript中的事件代理,由一道面試題講起,感興趣的小伙伴們可以參考一下
    2015-11-11
  • JavaScript 閉包機制詳解及實例代碼

    JavaScript 閉包機制詳解及實例代碼

    這篇文章主要介紹了JavaScript 閉包機制詳解及實例代碼的相關資料,需要的朋友可以參考下
    2016-10-10
  • JS中使用apply方法通過不同數(shù)量的參數(shù)調用函數(shù)的方法

    JS中使用apply方法通過不同數(shù)量的參數(shù)調用函數(shù)的方法

    這篇文章主要介紹了JS中使用apply方法通過不同數(shù)量的參數(shù)調用函數(shù)的方法的相關資料,需要的朋友可以參考下
    2016-05-05
  • JavaScript的作用域和塊級作用域概念理解

    JavaScript的作用域和塊級作用域概念理解

    任何一對花括號中的語句集都屬于一個塊,在這之中定義的所有變量在代碼塊外都是不可見的,我們稱之為塊級作用域
    2014-09-09
  • js獲取最近一周一個月三個月時間的簡單示例

    js獲取最近一周一個月三個月時間的簡單示例

    時間的獲取和格式化是我們經常遇到的問題,下面這篇文章主要給大家介紹了關于利用js如何獲取最近一周一個月三個月時間的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-12-12
  • Javascript基礎知識盲點總結之函數(shù)

    Javascript基礎知識盲點總結之函數(shù)

    函數(shù)是由事件驅動的或者當它被調用時執(zhí)行的可重復使用的代碼塊。這篇文章主要介紹了Javascript基礎知識盲點總結之函數(shù)的相關資料
    2016-05-05
  • JS中postcss插件實現(xiàn)vw適配的方法

    JS中postcss插件實現(xiàn)vw適配的方法

    PostCSS是一個用JavaScript編寫的插件工具,它可以幫助我們對CSS進行模塊化、自動化處理和優(yōu)化,這篇文章主要介紹了JS中postcss插件實現(xiàn)vw適配,需要的朋友可以參考下
    2025-01-01
  • JS中定位 position 的使用實例代碼

    JS中定位 position 的使用實例代碼

    本文通過實例代碼給大家介紹了JS中定位 position 的使用,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-08-08
  • 通過js給網頁加上水印背景實例

    通過js給網頁加上水印背景實例

    這篇文章主要介紹了通過js給網頁加上水印背景實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,,需要的朋友可以參考下
    2019-06-06
  • 最新評論