自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

掌握這八個(gè) Promise 并發(fā)控制技巧,性能大幅提升

開發(fā) 前端
當(dāng)我們需要同時(shí)處理多個(gè)異步任務(wù)時(shí),如何有效地控制 Promise 的并發(fā),就成為了一個(gè)影響性能和用戶體驗(yàn)的關(guān)鍵問題。

Promise 已經(jīng)成為 JavaScript 里處理異步操作的標(biāo)準(zhǔn)方式。然而,當(dāng)我們需要同時(shí)處理多個(gè)異步任務(wù)時(shí),如何有效地控制 Promise 的并發(fā),就成為了一個(gè)影響性能和用戶體驗(yàn)的關(guān)鍵問題。

假設(shè),你需要同時(shí)請求 100 個(gè)接口來獲取數(shù)據(jù)。如果一股腦地發(fā)起所有請求,可能會(huì)導(dǎo)致以下問題:

  • 瀏覽器并發(fā)限制:瀏覽器對同一域名的并發(fā)請求數(shù)量有限制(通常是 6-8 個(gè))。過多的請求會(huì)被阻塞,導(dǎo)致頁面加載緩慢
  • 服務(wù)器壓力過大:大量并發(fā)請求可能會(huì)給服務(wù)器帶來巨大的壓力,導(dǎo)致響應(yīng)變慢甚至崩潰
  • 資源競爭:多個(gè)異步任務(wù)同時(shí)訪問共享資源(例如數(shù)據(jù)庫連接、文件等),可能會(huì)導(dǎo)致資源競爭和死鎖
  • 用戶體驗(yàn)差:頁面長時(shí)間處于加載狀態(tài),用戶體驗(yàn)極差

因此,我們需要對 Promise 的并發(fā)進(jìn)行控制,在保證任務(wù)執(zhí)行效率的同時(shí),避免對系統(tǒng)資源造成過大的壓力。

Promise.all:并行執(zhí)行,統(tǒng)一返回

Promise.all 接收一個(gè) Promise 數(shù)組作為參數(shù),并行執(zhí)行所有 Promise,并在所有 Promise 都 fulfilled 后,返回一個(gè)包含所有結(jié)果的數(shù)組。

const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3])
  .then(results => {
    console.log(results); // 輸出:[1, 2, 3]
  });

適用場景: 多個(gè)異步任務(wù)之間沒有依賴關(guān)系,可以并行執(zhí)行。

注意: 如果其中任何一個(gè) Promise 被 rejected,Promise.all 會(huì)立即 rejected,并且只返回第一個(gè) rejected 的原因。

Promise.allSettled:并行執(zhí)行,返回所有狀態(tài)

Promise.allSettled 與 Promise.all 類似,也是并行執(zhí)行所有 Promise,但它會(huì)等待所有 Promise 都 settled(fulfilled 或 rejected),并返回一個(gè)包含所有 Promise 狀態(tài)和結(jié)果(或原因)的數(shù)組。

const promise1 = Promise.resolve(1);
const promise2 = Promise.reject("Error");
const promise3 = Promise.resolve(3);

Promise.allSettled([promise1, promise2, promise3])
  .then(results => {
    console.log(results);
    /* 輸出:
    [
      { status: 'fulfilled', value: 1 },
      { status: 'rejected', reason: 'Error' },
      { status: 'fulfilled', value: 3 }
    ]
    */
  });

適用場景: 需要獲取所有 Promise 的執(zhí)行結(jié)果,無論它們是 fulfilled 還是 rejected。

Promise.race:并行執(zhí)行,誰快用誰

Promise.race 接收一個(gè) Promise 數(shù)組作為參數(shù),并行執(zhí)行所有 Promise,只要其中任何一個(gè) Promise settled(fulfilled 或 rejected),Promise.race 就會(huì)返回該 Promise 的結(jié)果(或原因)。

適用場景: 只需要獲取最快完成的 Promise 的結(jié)果,例如設(shè)置請求超時(shí)。

Promise.any (ES2021):并行執(zhí)行,返回第一個(gè) fulfilled

Promise.any 接收一個(gè) Promise 數(shù)組作為參數(shù),并行執(zhí)行所有 Promise,只要其中任何一個(gè) Promise fulfilled,Promise.any 就會(huì)返回該 Promise 的結(jié)果。如果所有 Promise 都 rejected,則返回一個(gè) AggregateError。

適用場景: 需要獲取第一個(gè)成功的 Promise 的結(jié)果。

自定義并發(fā)控制函數(shù):限制最大并發(fā)數(shù)

Promise.all 等方法雖然可以并行執(zhí)行 Promise,但無法控制并發(fā)數(shù)量。我們可以自己實(shí)現(xiàn)一個(gè)函數(shù)來限制最大并發(fā)數(shù)。

使用示例:

原理:

  • tasks: 一個(gè)包含任務(wù)函數(shù)的數(shù)組,每個(gè)任務(wù)函數(shù)返回一個(gè) Promise。
  • limit: 最大并發(fā)數(shù)。
  • results: 存儲(chǔ)所有任務(wù)的結(jié)果。
  • running: 存儲(chǔ)當(dāng)前正在執(zhí)行的任務(wù)(Promise)。
  • current: 指向下一個(gè)要執(zhí)行的任務(wù)。
  • while 循環(huán):只要還有任務(wù)未執(zhí)行或有任務(wù)正在執(zhí)行,就繼續(xù)循環(huán)。
  • if 條件:如果當(dāng)前正在執(zhí)行的任務(wù)數(shù)量小于 limit 且還有任務(wù)未執(zhí)行,則取出下一個(gè)任務(wù)執(zhí)行,并將其添加到 running 數(shù)組中。
  • task.then():監(jiān)聽任務(wù)完成,將結(jié)果添加到 results 數(shù)組,并將任務(wù)從 running 數(shù)組中移除。
  • await Promise.race(running):如果當(dāng)前正在執(zhí)行的任務(wù)數(shù)量已達(dá)到 limit,則等待任意一個(gè)任務(wù)完成。
  • Promise.all(results): 等待所有任務(wù)執(zhí)行, 并返回結(jié)果。

使用第三方庫:p-limit、async-pool 等

有一些成熟的第三方庫可以更方便地實(shí)現(xiàn) Promise 并發(fā)控制,例如:

  • p-limit: 一個(gè)輕量級的 Promise 并發(fā)控制庫。

  • async-pool: 一個(gè)支持多種并發(fā)策略的 Promise 并發(fā)控制庫。

使用 Generator 函數(shù)和 yield 關(guān)鍵字

Generator 函數(shù)可以暫停和恢復(fù)執(zhí)行,結(jié)合 yield 關(guān)鍵字,可以實(shí)現(xiàn)更細(xì)粒度的并發(fā)控制。

async function* taskGenerator(tasks) {
  for (const task of tasks) {
    yield task();
  }
}

async function runTasks(tasks, limit) {
    let pool = [];
    let results = [];
    for await (let result of taskGenerator(tasks)) {
        pool.push(result);
        results.push(result);
    if (pool.length >= limit) {
        await Promise.race(pool);
        pool = pool.filter(p => p.status != 'fulfilled' && p.status != 'rejected') // 手動(dòng)維護(hù)
    }

    }
    return Promise.all(results)
}

使用消息隊(duì)列

對于非常大量的異步任務(wù), 且允許一定的延遲, 可以使用消息隊(duì)列(例如 RabbitMQ, Kafka 等), 將任務(wù)放入隊(duì)列, 然后由多個(gè)消費(fèi)者并行處理.

責(zé)任編輯:趙寧寧 來源: JavaScript
相關(guān)推薦

2024-03-06 13:56:00

項(xiàng)目awaitpromise

2025-02-07 15:01:49

Promise數(shù)組前端

2024-01-02 16:16:34

Promise前端

2025-02-17 08:50:00

CSS代碼JavaScript

2022-05-31 09:39:40

UI網(wǎng)格設(shè)計(jì)

2024-05-13 18:33:08

SQL日期函數(shù)

2022-05-30 00:04:16

開源Github技巧

2024-01-26 18:04:21

編輯器Code主題

2023-12-09 18:02:34

工具Code插件

2024-07-02 09:03:48

2010-09-02 16:14:20

CSS布局

2023-08-07 09:12:51

權(quán)限SpringSecurity

2025-01-10 08:38:16

2012-10-29 11:01:17

2022-04-07 11:04:31

RocketMQBrokerConsumer

2022-05-26 00:33:29

權(quán)限TienChin項(xiàng)目

2022-12-15 16:38:17

2024-03-21 09:58:27

ExtractTypeScript工具類型

2024-04-01 07:51:49

Exclude?工具類型TypeScript

2013-09-05 13:49:18

WordPress速度
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號