欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何基于JS實(shí)現(xiàn)Ajax并發(fā)請(qǐng)求的控制詳解

 更新時(shí)間:2021年09月06日 09:17:00   作者:麥忙  
通常為了減少頁面加載時(shí)間,先把核心內(nèi)容顯示處理,頁面加載完成后再發(fā)送ajax請(qǐng)求獲取其他數(shù)據(jù),這時(shí)就可能產(chǎn)生多個(gè)ajax請(qǐng)求,為了用戶體驗(yàn),最好是發(fā)送并行請(qǐng)求,這篇文章主要給大家介紹了關(guān)于如何基于JS實(shí)現(xiàn)Ajax并發(fā)請(qǐng)求控制的相關(guān)文章,需要的朋友可以參考下

前言

最近看到一個(gè)面試題,當(dāng)然了,就是這篇文章的標(biāo)題,Ajax的并發(fā)請(qǐng)求的控制,感覺挺有意思的,在社區(qū)看了下,應(yīng)該是字節(jié)的面試題,也挺多大佬對(duì)這個(gè)進(jìn)行了總結(jié),都看了下,于是自己也想試著總結(jié)下,代碼文末會(huì)全部貼出,如有不足,請(qǐng)指出!

Ajax的串行與并行

  • 串行:一般業(yè)務(wù)需求是下個(gè)接口需要用到上個(gè)接口的返回的數(shù)據(jù),前端常用的請(qǐng)求庫是Axios,本身就是基于Promise的HTTP庫,我們直接采用鏈?zhǔn)秸{(diào)用,或者采用Async Await 的方式就可以實(shí)現(xiàn),就不做演示了
  • 并行:就是多個(gè)請(qǐng)求同時(shí)發(fā)生,一般情況會(huì)用于當(dāng)所有數(shù)據(jù)都拿到后進(jìn)行渲染頁面,或者其他的操作,主要還是基于Promise.all實(shí)現(xiàn)方式如下

上面模擬實(shí)現(xiàn)了基于Promise.all的并行操作,打印結(jié)果入下

是不是覺得的這就結(jié)束了,不存在的?接下來才是正菜,我們?cè)囅胗蟹N情況,一個(gè)頁面中需要同時(shí)發(fā)送上萬個(gè)請(qǐng)求,全部成功后再去做一些操作,這樣會(huì)導(dǎo)致什么后果呢?代碼無法執(zhí)行,內(nèi)存溢出,哎~這個(gè)時(shí)候就回到了我們文章的主題上了,如何對(duì)Ajax并發(fā)請(qǐng)求的控制呢?我讓他一次性只能輸出一定數(shù)量的請(qǐng)求,直到所有的都成功為止,接下來我將用兩種方法實(shí)現(xiàn)這個(gè)操作,望讀者朋友們不吝賜教

Ajax的并發(fā)請(qǐng)求控制的兩大解決方案

基于Promise遞歸實(shí)現(xiàn)

以下的兩種方法都是需要用到上圖中的那個(gè)Tasks數(shù)組的,請(qǐng)大家記住它,第一中基于Promise的方法,大致思路是:當(dāng)你傳入一個(gè)并發(fā)量pool時(shí),會(huì)創(chuàng)建pool個(gè)工作區(qū),每一個(gè)工作區(qū)回去拿對(duì)應(yīng)的任務(wù)(請(qǐng)求)去執(zhí)行,成功后保存,然后繼續(xù)去拿任務(wù)(請(qǐng)求),直到工作區(qū)沒有任務(wù)了,當(dāng)然了,失敗直接終止, 大致思路就是這樣,下面我對(duì)每一行代碼進(jìn)行了注釋,請(qǐng)笑納

基于Class實(shí)現(xiàn)

第二種方法是基于Class來實(shí)現(xiàn)的,和上面的區(qū)別在于這個(gè)只創(chuàng)造一個(gè)工作區(qū),大致思路:創(chuàng)建一個(gè)工作區(qū)用于執(zhí)行任務(wù)(請(qǐng)求),然后將所有任務(wù)都推入,但是沒次只能執(zhí)行對(duì)應(yīng)的并發(fā)數(shù),當(dāng)小于并發(fā)數(shù)市,繼續(xù)去拿任務(wù)執(zhí)行它,直到?jīng)]有任務(wù)(請(qǐng)求)為止, 就是這樣,下面是具體實(shí)現(xiàn)

代碼展示

這里把這兩種方法的實(shí)現(xiàn)代碼貼出

    const delay = function delay(interval) {
      return new Promise((res,rej) => {
        setTimeout(() => {
          res(interval)
        }, interval);
      })
    }


    let tasks = [() => {
      return delay(1000)
    },() => {
      return delay(1003)
    },() => {
      return delay(1005)
    },() => {
      return delay(1002)
    },() => {
      return delay(1004)
    },() => {
      return delay(1006)
    }]

    // 通過Promise.all實(shí)現(xiàn)并行
    Promise.all(tasks.map(task => task())).then(res => {
      console.log(res);
    })

    // 基于Promise實(shí)現(xiàn)

    function creatRequest(tasks,pool) {
      // 每次控制的發(fā)送請(qǐng)求的數(shù)量pool
      pool = pool || 5
      // 用于存儲(chǔ)每一次請(qǐng)求的結(jié)果(按順序進(jìn)行存貯)
      let results = [],
      // together 用于創(chuàng)建工作區(qū),當(dāng)pool傳入的是幾,我們就對(duì)應(yīng)的創(chuàng)建幾個(gè)工作區(qū)
      // 也就是創(chuàng)建一個(gè)長(zhǎng)度為pool且值為null的一個(gè)數(shù)組
          together = new Array(pool).fill(null),
      // index為每次獲取的任務(wù)值
          index = 0;
      together = together.map(() => {
        // 基于Promise進(jìn)行管理
        return new Promise((resolve,reject) => {
          // 創(chuàng)建一個(gè)函數(shù),進(jìn)來立刻執(zhí)行
          const run = function run() {
            // 如果任務(wù)池已經(jīng)空了,說明請(qǐng)求發(fā)送完成了,直接成功
            if(index >= tasks.length) {
              resolve()
              return 
            }
            // 先將index保存一下用于存儲(chǔ)當(dāng)前成功請(qǐng)求的結(jié)果
            let old_index = index,
            // 獲取當(dāng)前發(fā)送的請(qǐng)求,然后把index進(jìn)行累加,所以上面會(huì)把index保存起來
            // 這里index++ 是先運(yùn)算后累加的,而++index則相反,先累加后運(yùn)算
                task = tasks[index++];
            // 執(zhí)行請(qǐng)求
            task().then(result => {
            // 將成功結(jié)果保存
              results[old_index] = result
            // 遞歸繼續(xù)執(zhí)行,也就是繼續(xù)拿到任務(wù)到工作區(qū)執(zhí)行
              run();
            }).catch(reason => {
              reject(reason)
            })
          }
          // 立即執(zhí)行
          run()
        })
      })
      // 用Promise.all管控工作區(qū),也就是每次并發(fā)兩個(gè)請(qǐng)求
      return Promise.all(together).then(() => results)
    }


    creatRequest(tasks,2).then(results => {
      // 都成功,整體才成功,按順序存儲(chǔ)結(jié)果
      console.log('成功',results);
    }).catch(resolve => {
      // 只要有一個(gè)失敗,整體失敗
      console.log('失敗');
    })



    // 基于Class實(shí)現(xiàn)
    function creatRequest(tasks,pool,callback) {
      // 參數(shù)的限制與驗(yàn)證
      if(typeof pool === 'function') {
        callback = pool;
        pool = 5
      }
      if(typeof pool !== 'number') pool = 5
      if(typeof callback !== 'function') callback = function () {}
      // -------
      class TaskQueue {
        // 正在運(yùn)行的個(gè)數(shù)
        runing = 0;
        // 將所有任務(wù)所存在的隊(duì)列
        queue = [];
        // 存儲(chǔ)執(zhí)行任務(wù)(請(qǐng)求)的結(jié)果
        results = [];
        pushTask(task) {
          let self = this
          // 將任務(wù)推入工作區(qū)
          self.queue.push(task)
          // 執(zhí)行發(fā)送請(qǐng)求的邏輯
          self.next()
        }
        next() {
          let self = this
          // 當(dāng)正在執(zhí)行的任務(wù)數(shù)小于并發(fā)量的時(shí)候繼續(xù)去拿任務(wù)執(zhí)行
          while(self.runing < pool && self.queue.length) {
            self.runing++;
            // 相當(dāng)于拿一個(gè)任務(wù)刪除一個(gè)任務(wù)
            let task = self.queue.shift();
            // 執(zhí)行請(qǐng)求
            task().then(result => {
              // 將執(zhí)行結(jié)果保存
              self.results.push(result)
            }).finally(() => {
              // 將正在運(yùn)行的個(gè)數(shù)清除
              self.runing--
              // 繼續(xù)執(zhí)行請(qǐng)求
              self.next()
            })
          }
          // 當(dāng)沒有任務(wù)了循環(huán)結(jié)束
          if(self.runing === 0) callback(self.results)
        }


      }
      // 實(shí)例化
      let TQ = new TaskQueue()
      tasks.forEach(task => TQ.pushTask(task))
    }


    creatRequest(tasks,2,results=> {
      console.log(results);
    })

總結(jié)

以上就是對(duì)這套面試題的總結(jié)了,也是自己做下記錄,后續(xù)會(huì)不斷的更新前端方面的文章,最后還是希望各位前端的小伙伴們都能堅(jiān)持學(xué)習(xí),技術(shù)不斷提升,加油吧,騷年?。?!

到此這篇關(guān)于如何基于JS實(shí)現(xiàn)Ajax并發(fā)請(qǐng)求控制的文章就介紹到這了,更多相關(guān)JS實(shí)現(xiàn)Ajax并發(fā)請(qǐng)求控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決layui的radio屬性或別的屬性沒顯示出來的問題

    解決layui的radio屬性或別的屬性沒顯示出來的問題

    今天小編就為大家分享一篇解決layui的radio屬性或別的屬性沒顯示出來的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • JavaScript encodeURI 和encodeURIComponent

    JavaScript encodeURI 和encodeURIComponent

    encodeURI和encodeURIComponet函數(shù)都是javascript中用來對(duì)URI進(jìn)行編碼,將相關(guān)參數(shù)轉(zhuǎn)換成UTF-8編碼格式的數(shù)據(jù)。URI在進(jìn)行定位跳轉(zhuǎn)時(shí),參數(shù)里面的中文、日文等非ASCII編碼都會(huì)進(jìn)行編碼轉(zhuǎn)換
    2015-12-12
  • JS實(shí)現(xiàn)的顏色實(shí)時(shí)漸變效果完整實(shí)例

    JS實(shí)現(xiàn)的顏色實(shí)時(shí)漸變效果完整實(shí)例

    這篇文章主要介紹了JS實(shí)現(xiàn)的顏色實(shí)時(shí)漸變效果,結(jié)合實(shí)例形式分析了JavaScript結(jié)合時(shí)間函數(shù)定時(shí)觸發(fā)動(dòng)態(tài)改變頁面元素屬性的相關(guān)技巧,需要的朋友可以參考下
    2016-03-03
  • JS?中的?Event?Loop?是什么你真的懂

    JS?中的?Event?Loop?是什么你真的懂

    Event Loop,簡(jiǎn)單翻譯就是?事件循環(huán),是 JS 語言下實(shí)現(xiàn)運(yùn)行時(shí)的一個(gè)機(jī)制,這篇文章主要介紹了JS?中的?Event?Loop?的基本知識(shí),需要的朋友可以參考下
    2022-06-06
  • JavaScript仿淘寶頁面圖片滾動(dòng)加載及刷新回頂部的方法解析

    JavaScript仿淘寶頁面圖片滾動(dòng)加載及刷新回頂部的方法解析

    這篇文章主要介紹了JavaScript仿淘寶頁面圖片滾動(dòng)加載及刷新回頂部的方法解析,包括懶加載和onbeforeunload等要點(diǎn)的理解,需要的朋友可以參考下
    2016-05-05
  • javascript的正則匹配方法學(xué)習(xí)

    javascript的正則匹配方法學(xué)習(xí)

    這篇文章主要為大家詳細(xì)介紹了javascript的正則匹配方法,幫助大家更快更高效的學(xué)習(xí)javascript正則的相關(guān)內(nèi)容,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 詳解webpack進(jìn)階之loader篇

    詳解webpack進(jìn)階之loader篇

    本篇文章主要介紹了詳解webpack進(jìn)階之loader篇,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • 詳解JavaScript的函數(shù)簡(jiǎn)介

    詳解JavaScript的函數(shù)簡(jiǎn)介

    這篇文章主要為大家介紹了JavaScript的函數(shù)簡(jiǎn)介,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • 基于JavaScript實(shí)現(xiàn)類名的添加與移除

    基于JavaScript實(shí)現(xiàn)類名的添加與移除

    本文給大家分享javascript實(shí)現(xiàn)類名的添加與移除功能,需要的朋友參考下吧
    2017-04-04
  • JavaScript 獲得選中文本內(nèi)容的方法

    JavaScript 獲得選中文本內(nèi)容的方法

    今天希望實(shí)現(xiàn)一個(gè),直接在網(wǎng)頁上選中文本,點(diǎn)擊收藏夾的鏈接(javascript)即可彈出新窗口(類似“百度搜藏”和“QQ書簽”),新窗口中的文本框即顯示了選中的文本。
    2009-02-02

最新評(píng)論