私の連絡先情報
郵便メール:
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
フロントエンドが同時リクエストを制御する必要があるのは、必要なデータのリクエストに複数回かかる場合です。たとえば、インターフェイスが一度に大量のデータを返す場合、ブラウザはレンダリング中にスタックしたりクラッシュしたりする可能性があります。このとき、スタックやクラッシュを回避するために、バッチで 6 つのリクエストを同時に発行できます。 。
では、フロントエンドは同時リクエストをどのように制御するのでしょうか?
たとえば、20 件のリクエストがある場合、次のようにする必要があります。 3
最初のグループがリクエストを完了すると、2 番目のグループがリクエストされ、以下同様に続きます。
重要なアイデアは、リクエスト メソッドとリクエスト パラメータを配列に格納し、一度に 3 つずつリクエストし、リクエストが完了した後に次の 3 つをリクエストすることです。リクエストの各グループが返された後、結果が保存され、すべてのリクエストが返された後、すべての結果が返されます。
pControl
: 同時リクエスト コントローラー。同時実行の最大数を渡します。
add
: リクエストとパラメータを追加します。
start
: リクエストの開始、Promise の返却、リクエスト完了後のパス.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()
})
}
})
}
}
pControl
: この関数は、次の内容を含むオブジェクトを返します。 add
そしてstart
2つの方法、add
タスクとパラメータを追加するために使用されます。start
リクエストを開始するために使用される、クロージャです。
runAllTasks
: を返しますpromise
、そして、new Promise
内部的に再帰的に実行されるrunTask
、runTask が渡されるPromise.all
同時リクエストを実行するPromise.all().then()
もう一度電話してくださいrunTask
、返される要求の 1 セットを実装し、次に 2 番目の要求セットを実行します。
集団待機を実現する鍵となるのは、
.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
}
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
}
for
、 while
、 for...of
命令型ループ構造の場合、ループ内で待機効果を実現したい場合は、次を使用する必要があります。async
ループ内の関数ラッパーawait
、故障中.then
。
forEach
、 map
、 filter
これらの関数ループ構造は同期的であり、待機をサポートしていないため、これらの関数ループ構造は待機効果をサポートしません。
async
そして循环
+await
組み合わせてループ間の待機効果を実現します。
promise.then
そして递归
組み合わせてループ間の待機効果を実現します。
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)
})
開始コールバックは何をするのでしょうか?
ユーザーにとって、現在の同時リクエストの結果を取得し、完了の進行状況を計算するのに便利です。
p-control
npmパッケージのリリースアクセス可能な npm i p-control
ダウンロードして使用してください。
.then
再帰と組み合わせて、非同期タスク間の待機を実現します。for
、while
ループを待って、async
+ await
非同期タスク間の待機を実現するために組み合わせて使用されます。Promise.all
複数の非同期タスクを実装して、同時に実行します。