Teknologian jakaminen

Kuinka käyttöliittymä hallitsee samanaikaisia ​​pyyntöjä

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Milloin käyttöliittymän on ohjattava samanaikaisia ​​pyyntöjä, kun vaadittujen tietojen pyytäminen kestää useita kertoja? Esimerkiksi jos käyttöliittymä palauttaa suuren määrän dataa kerralla, selain jumissa renderöinnissa tai jopa kaatuu. Tällä hetkellä voimme lähettää 6 pyyntöä samanaikaisesti erissä välttääksemme jumiutumisen tai kaatumisen. .

Joten miten käyttöliittymä hallitsee samanaikaisia ​​pyyntöjä?

Keskeisiä ideoita samanaikaisten pyyntöjen käyttöliittymän hallintaan

Jos pyyntöjä on esimerkiksi 20, sinun on noudatettava sitä 3 Kun ensimmäinen ryhmä on suorittanut pyynnön, toinen ryhmä pyytää ja niin edelleen.

Keskeisenä ideana on tallentaa pyyntömenetelmä ja pyyntöparametrit taulukkoon, sitten pyytää 3 kerrallaan ja sitten pyytää seuraavaa 3 pyynnön valmistuttua. Kun jokainen pyyntöryhmä palaa, tulokset tallennetaan, ja kun kaikki pyynnöt on palautettu, kaikki tulokset palautetaan.

api suunnittelu

pControl : Samanaikaisen pyynnön ohjain, joka läpäisee enimmäismäärän samanaikaisuuksia;
add : Lisää pyyntö ja parametrit;
start : Aloita pyyntö, palauta lupaus, hyväksy, kun pyyntö on suoritettu.then Hanki kaikki tulokset;

Koodi

function pControl(limit) {
  const taskQueue = [] // {task: Function, params: any[]}[]
  return {
    add,
    start
  }

  function add(task, params) {
    taskQueue.push({
      task,
      params
    })
  }

  function start() {
    return runAllTasks()
  }

  function runAllTasks() {
    const allResults = []
    return new Promise((resolve) => {

      runTask()

      function runTask() {
        if (taskQueue.length === 0) {
          // 递归结束
          return resolve(allResults)
        }
        const needRunSize = Math.min(taskQueue.length, limit)
        const tasks = taskQueue.splice(0, needRunSize)
        const promises = tasks.map(({
          task,
          params
        }) => task(params))
        Promise.all(promises).then((resList) => {
          allResults.push(...resList)
          // NOTE 递归调用的位置很关键
          runTask()
        })
      }
    })
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

Avainkoodin tulkinta

  • pControl: Tämä funktio palauttaa objektin, joka sisältää add jastart Kaksi tapaa,add Käytetään tehtävien ja parametrien lisäämiseen,start Käytetään pyynnön aloittamiseen, se on sulkeminen.

  • runAllTasks: palauttaa apromise, ja sitten sisäännew PromiseSisäisesti suoritettu rekursiivisestirunTask, RunTask kulkeePromise.all Suorita samanaikaiset pyynnöt sisäänPromise.all().then() soita uudelleenrunTask, toteuttaa yksi palautuspyyntösarja ja suorittaa sitten toinen pyyntösarja.

Avain ryhmän odottamisen toteuttamiseen on .then rekursiivinen puhelu.

Ajatteleminen: Voidaanko runAllTasks toteuttaa silmukan avulla?

Kyllä, pitää käyttää async 和 for 循环 + await

async function runAllTasks2() {
  const allResults = []
  const groupArr = []
  let startIndex = 0
  // 划分分组
  while (startIndex < taskQueue.length) {
    const arr = taskQueue.slice(startIndex, startIndex + limit)
    groupArr.push(arr)
    startIndex += limit
  }
  for (let index = 0; index < groupArr.length; index++) {
    const pList = groupArr[index].map(({
      task,
      params
    }) => task(params))
    const res = await Promise.all(pList)
    allResults.push(...res)
  }
  return allResults
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

Ei voida käyttää silmukassa .then , muuten seuraava silmukka ei odota edellistä silmukkaa.

käyttää for of Iteratiivinen toteutus:

async function runAllTasks2() {
  const allResults = []
  const groupArr = []
  let startIndex = 0
  // 划分分组
  while (startIndex < taskQueue.length) {
    const arr = taskQueue.slice(startIndex, startIndex + limit)
    groupArr.push(arr)
    startIndex += limit
  }
  // 迭代分组
  const it = groupArr.entries()
  for (const [key, value] of it) {
    const pList = value.map(({
      task,
      params
    }) => task(params))
    const res = await Promise.all(pList)
    allResults.push(...res)
  }
  return allResults
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Kuinka käyttää silmukoita ja lupausta yhdessä?

forwhilefor...of Pakollisten silmukkarakenteiden kohdalla, jos haluat saavuttaa odottavan vaikutuksen silmukassa, sinun on käytettäväasync funktion kääre silmukassaawait ,Poissa käytöstä.then

forEachmapfilter Tällaiset toiminnalliset silmukkarakenteet eivät tue odotusefektejä, koska nämä toiminnalliset silmukkarakenteet ovat synkronisia eivätkä tue odottelua.

async ja循环 + await Yhdistetty odotusvaikutuksen saavuttamiseksi silmukoiden välillä.

promise.then ja递归 Yhdistetty odotusvaikutuksen saavuttamiseksi silmukoiden välillä.

Paranna APIa käytön helpottamiseksi

  1. Aseta oletusparametrit: annapControlAseta sopiva oletusarvo, aseta arvoksi6, koska sama verkkotunnus on sisällä, selaimen samanaikaiset pyynnöt ovat 6.
  2. aloita takaisinsoitto: Takaisinsoiton kautta saat kunkin ryhmän pyyntötulokset ja tiedät tällä hetkellä suoritettujen pyyntöjen määrän.

Nämä kaksi parannusta ovat yksinkertaisia. Katsotaanpa ensin käyttöä:

const asyncTaskControl = pControl() // 默认 6 
asyncTaskControl.add(task, params1)
asyncTaskControl.add(task, params2)
// ...
asyncTaskControl.add(task, params10)

asyncTaskControl.start((res, doneSize) => {
  // 获取每组请求的结果 和当前完成了多少请求
  console.log(res) // [{index:number,result:data}] 
  console.log(doneSize)
}).then(allResults => {
  // 所有请求结果
  console.log(allResults)
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Mitä aloitussoitto tekee?

Käyttäjien on kätevää saada nykyisten samanaikaisten pyyntöjen tulokset ja laskea valmistumisen edistyminen.

Kapseloi yllä olevat funktiot p-control npm paketin julkaisu

npm: p-ohjaus

saatavilla npm i p-control Lataa ja käytä.

yhteenveto

  • .then Yhdessä rekursion kanssa odottamisen saavuttamiseksi asynkronisten tehtävien välillä;
  • forwhileOdota silmukkaa jaasync + awaitKäytetään yhdessä odottamaan asynkronisten tehtävien välillä;
  • käyttääPromise.allToteuta useita asynkronisia tehtäviä suoritettavaksi samanaikaisesti.