Κοινή χρήση τεχνολογίας

Πώς η διεπαφή ελέγχει ταυτόχρονα αιτήματα

2024-07-12

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

Πότε χρειάζεται η διεπαφή να ελέγχει ταυτόχρονα αιτήματα Όταν χρειάζονται πολλές φορές για να ζητηθούν τα απαιτούμενα δεδομένα; Για παράδειγμα, εάν η διεπαφή επιστρέφει μεγάλο όγκο δεδομένων ταυτόχρονα, το πρόγραμμα περιήγησης θα κολλήσει στην απόδοση ή ακόμη και θα κολλήσει αυτήν τη στιγμή, μπορούμε να εκδίδουμε 6 αιτήματα ταυτόχρονα σε παρτίδες, ώστε να αποφευχθεί η κολλήσει ή η κατάρρευση. .

Πώς λοιπόν η διεπαφή ελέγχει ταυτόχρονα αιτήματα;

Βασικές ιδέες για τον έλεγχο της διεπαφής των ταυτόχρονων αιτημάτων

Για παράδειγμα, εάν υπάρχουν 20 αιτήματα, πρέπει να ακολουθήσετε 3 Αφού η πρώτη ομάδα ολοκληρώσει το αίτημα, θα ζητηθεί η δεύτερη ομάδα και ούτω καθεξής.

Η βασική ιδέα είναι να αποθηκεύσετε τη μέθοδο αιτήματος και τις παραμέτρους αιτήματος σε έναν πίνακα, στη συνέχεια να ζητήσετε 3 κάθε φορά και στη συνέχεια να ζητήσετε τις επόμενες 3 μετά την ολοκλήρωση του αιτήματος. Μετά την επιστροφή κάθε ομάδας αιτημάτων, τα αποτελέσματα αποθηκεύονται και μετά την επιστροφή όλων των αιτημάτων, επιστρέφονται όλα τα αποτελέσματα.

σχέδιο api

pControl : Ελεγκτής ταυτόχρονων αιτημάτων, περνώντας τον μέγιστο αριθμό ταυτόχρονων.
add : Προσθήκη αιτήματος και παραμέτρων.
start : Αίτημα έναρξης, υπόσχεση επιστροφής, πέρασμα μετά την ολοκλήρωση του αιτήματος.then Λάβετε όλα τα αποτελέσματα.

Κώδικας

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

Ερμηνεία κωδικού κλειδιού

  • pControl: Αυτή η συνάρτηση επιστρέφει ένα αντικείμενο που περιέχει add καιstart Δύο μέθοδοι,add Χρησιμοποιείται για την προσθήκη εργασιών και παραμέτρων,start Χρησιμοποιείται για την έναρξη του αιτήματος, είναι ένα κλείσιμο.

  • runAllTasks: επιστρέφει αpromise, και μετά μέσαnew PromiseΕσωτερικά εκτελείται αναδρομικάrunTask, περνάει το runTaskPromise.all Εκτελέστε ταυτόχρονες αιτήσεις σεPromise.all().then() Ξαναπάρε τηλέφωνοrunTask, εφαρμόστε ένα σύνολο αιτημάτων για επιστροφή και, στη συνέχεια, εκτελέστε το δεύτερο σύνολο αιτημάτων.

Το κλειδί για την πραγματοποίηση της ομαδικής αναμονής είναι να .then αναδρομική κλήση.

Σκέψη: Μπορεί το runAllTasks να υλοποιηθεί με χρήση βρόχου;

Ναι, πρέπει να χρησιμοποιηθεί 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

Δεν μπορεί να χρησιμοποιηθεί σε βρόχο for .then , διαφορετικά ο επόμενος βρόχος δεν θα περιμένει τον προηγούμενο βρόχο.

χρήση for of Επαναληπτική υλοποίηση:

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

Πώς να χρησιμοποιήσετε τους βρόχους και το Promise μαζί;

forwhilefor...of Για δομές επιτακτικού βρόχου, εάν θέλετε να επιτύχετε το εφέ αναμονής στον βρόχο, πρέπει να χρησιμοποιήσετεasync περιτύλιγμα λειτουργίας σε βρόχοawait ,Εκτός λειτουργίας.then

forEachmapfilter Οι δομές λειτουργικού βρόχου όπως αυτές δεν υποστηρίζουν εφέ αναμονής, επειδή αυτές οι δομές λειτουργικού βρόχου είναι σύγχρονες και δεν υποστηρίζουν αναμονή.

async και循环 + await Συνδυάζεται για την επίτευξη του εφέ αναμονής μεταξύ των βρόχων.

promise.then και递归 Συνδυάζεται για την επίτευξη του εφέ αναμονής μεταξύ των βρόχων.

Βελτιώστε το API για να το κάνετε πιο εύκολο στη χρήση

  1. Ορισμός προεπιλεγμένων παραμέτρων: δίνωpControlΟρίστε μια κατάλληλη προεπιλεγμένη τιμή, ορίστε σε6, επειδή υπάρχει το ίδιο όνομα τομέα, τα ταυτόχρονα αιτήματα του προγράμματος περιήγησης είναι 6.
  2. έναρξη της επανάκλησης: Μέσω της επανάκλησης, μπορείτε να λάβετε τα αποτελέσματα των αιτημάτων κάθε ομάδας και να γνωρίζετε τον αριθμό των αιτημάτων που έχουν ολοκληρωθεί αυτήν τη στιγμή.

Αυτές οι δύο βελτιώσεις είναι απλές. Ας δούμε πρώτα τη χρήση:

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

Τι κάνει η έναρξη επανάκλησης;

Είναι βολικό για τους χρήστες να λαμβάνουν τα αποτελέσματα των τρεχόντων ταυτόχρονων αιτημάτων και να υπολογίζουν την πρόοδο ολοκλήρωσης.

Ενθυλακώστε τις παραπάνω συναρτήσεις σε p-control έκδοση πακέτου npm

npm: p-control

προσιτός npm i p-control Λήψη και χρήση.

περίληψη

  • .then Σε συνδυασμό με την αναδρομή για την επίτευξη αναμονής μεταξύ ασύγχρονων εργασιών.
  • forwhileΠεριμένετε για το βρόχο καιasync + awaitΧρησιμοποιείται σε συνδυασμό για την επίτευξη αναμονής μεταξύ ασύγχρονων εργασιών.
  • χρήσηPromise.allΕφαρμόστε πολλαπλές ασύγχρονες εργασίες για ταυτόχρονη εκτέλεση.