久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      什么是并發(fā)控制?JavaScript中如何實(shí)現(xiàn)并發(fā)控制?

      什么是并發(fā)控制?JavaScript中如何實(shí)現(xiàn)并發(fā)控制?

      在日常開發(fā)過程中,你可能會遇到并發(fā)控制的場景,比如控制請求并發(fā)數(shù)。那么在 JavaScript 中如何實(shí)現(xiàn)并發(fā)控制呢?在回答這個問題之前,我們來簡單介紹一下并發(fā)控制。

      假設(shè)有 6 個待辦任務(wù)要執(zhí)行,而我們希望限制同時執(zhí)行的任務(wù)個數(shù),即最多只有 2 個任務(wù)能同時執(zhí)行。當(dāng) 正在執(zhí)行任務(wù)列表 中的任何 1 個任務(wù)完成后,程序會自動從 待辦任務(wù)列表 中獲取新的待辦任務(wù)并把該任務(wù)添加到 正在執(zhí)行任務(wù)列表 中。為了讓大家能夠更直觀地理解上述的過程,阿寶哥特意畫了以下 3 張圖:

      1.1 階段一

      什么是并發(fā)控制?JavaScript中如何實(shí)現(xiàn)并發(fā)控制?

      1.2 階段二

      什么是并發(fā)控制?JavaScript中如何實(shí)現(xiàn)并發(fā)控制?

      1.3 階段三

      什么是并發(fā)控制?JavaScript中如何實(shí)現(xiàn)并發(fā)控制?

      好的,介紹完并發(fā)控制之后,阿寶哥將以 Github 上 async-pool 這個庫來介紹一下異步任務(wù)并發(fā)控制的具體實(shí)現(xiàn)。

      async-pool:https://github.com/rxaviers/async-pool

      Run multiple promise-returning & async functions with limited concurrency using native ES6/ES7。

      二、并發(fā)控制的實(shí)現(xiàn)

      async-pool 這個庫提供了 ES7 和 ES6 兩種不同版本的實(shí)現(xiàn),在分析其具體實(shí)現(xiàn)之前,我們來看一下它如何使用。

      2.1 asyncPool 的使用

      const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i)); await asyncPool(2, [1000, 5000, 3000, 2000], timeout);

      在以上代碼中,我們使用 async-pool 這個庫提供的 asyncPool 函數(shù)來實(shí)現(xiàn)異步任務(wù)的并發(fā)控制。 asyncPool 函數(shù)的簽名如下所示:

      function asyncPool(poolLimit, array, iteratorFn){ ... }

      該函數(shù)接收 3 個參數(shù):

      • poolLimit(數(shù)字類型):表示限制的并發(fā)數(shù);
      • array(數(shù)組類型):表示任務(wù)數(shù)組;
      • iteratorFn(函數(shù)類型):表示迭代函數(shù),用于實(shí)現(xiàn)對每個任務(wù)項進(jìn)行處理,該函數(shù)會返回一個 Promise 對象或異步函數(shù)。

      對于以上示例來說,在使用了 asyncPool 函數(shù)之后,對應(yīng)的執(zhí)行過程如下所示:

      const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i)); await asyncPool(2, [1000, 5000, 3000, 2000], timeout); // Call iterator (i = 1000) // Call iterator (i = 5000) // Pool limit of 2 reached, wait for the quicker one to complete... // 1000 finishes // Call iterator (i = 3000) // Pool limit of 2 reached, wait for the quicker one to complete... // 3000 finishes // Call iterator (i = 2000) // Itaration is complete, wait until running ones complete... // 5000 finishes // 2000 finishes // Resolves, results are passed in given array order `[1000, 5000, 3000, 2000]`.

      通過觀察以上的注釋信息,我們可以大致地了解 asyncPool 函數(shù)內(nèi)部的控制流程。下面我們先來分析 asyncPool 函數(shù)的 ES7 實(shí)現(xiàn)。

      關(guān)注「全棧修仙之路」閱讀阿寶哥原創(chuàng)的 4 本免費(fèi)電子書(累計下載 3萬+)及 50 幾篇 TS 系列教程。

      2.2 asyncPool ES7 實(shí)現(xiàn)

      async function asyncPool(poolLimit, array, iteratorFn) {   const ret = []; // 存儲所有的異步任務(wù)   const executing = []; // 存儲正在執(zhí)行的異步任務(wù)   for (const item of array) {     // 調(diào)用iteratorFn函數(shù)創(chuàng)建異步任務(wù)     const p = Promise.resolve().then(() => iteratorFn(item, array));     ret.push(p); // 保存新的異步任務(wù)      // 當(dāng)poolLimit值小于或等于總?cè)蝿?wù)個數(shù)時,進(jìn)行并發(fā)控制     if (poolLimit <= array.length) {       // 當(dāng)任務(wù)完成后,從正在執(zhí)行的任務(wù)數(shù)組中移除已完成的任務(wù)       const e = p.then(() => executing.splice(executing.indexOf(e), 1));       executing.push(e); // 保存正在執(zhí)行的異步任務(wù)       if (executing.length >= poolLimit) {         await Promise.race(executing); // 等待較快的任務(wù)執(zhí)行完成       }     }   }   return Promise.all(ret); }

      在以上代碼中,充分利用了 Promise.allPromise.race 函數(shù)特點(diǎn),再結(jié)合 ES7 中提供的 async await 特性,最終實(shí)現(xiàn)了并發(fā)控制的功能。利用 await Promise.race(executing); 這行語句,我們會等待 正在執(zhí)行任務(wù)列表 中較快的任務(wù)執(zhí)行完成之后,才會繼續(xù)執(zhí)行下一次循環(huán)。

      asyncPool ES7 實(shí)現(xiàn)相對比較簡單,接下來我們來看一下不使用 async await 特性要如何實(shí)現(xiàn)同樣的功能。

      2.3 asyncPool ES6 實(shí)現(xiàn)

      function asyncPool(poolLimit, array, iteratorFn) {   let i = 0;   const ret = []; // 存儲所有的異步任務(wù)   const executing = []; // 存儲正在執(zhí)行的異步任務(wù)   const enqueue = function () {     if (i === array.length) {       return Promise.resolve();     }     const item = array[i++]; // 獲取新的任務(wù)項     const p = Promise.resolve().then(() => iteratorFn(item, array));     ret.push(p);      let r = Promise.resolve();      // 當(dāng)poolLimit值小于或等于總?cè)蝿?wù)個數(shù)時,進(jìn)行并發(fā)控制     if (poolLimit <= array.length) {       // 當(dāng)任務(wù)完成后,從正在執(zhí)行的任務(wù)數(shù)組中移除已完成的任務(wù)       const e = p.then(() => executing.splice(executing.indexOf(e), 1));       executing.push(e);       if (executing.length >= poolLimit) {         r = Promise.race(executing);        }     }       // 正在執(zhí)行任務(wù)列表 中較快的任務(wù)執(zhí)行完成之后,才會從array數(shù)組中獲取新的待辦任務(wù)     return r.then(() => enqueue());   };   return enqueue().then(() => Promise.all(ret)); }

      在 ES6 的實(shí)現(xiàn)版本中,通過內(nèi)部封裝的 enqueue 函數(shù)來實(shí)現(xiàn)核心的控制邏輯。當(dāng) Promise.race(executing) 返回的 Promise 對象變成已完成狀態(tài)時,才會調(diào)用 enqueue 函數(shù),從 array 數(shù)組中獲取新的待辦任務(wù)。

      三、阿寶哥有話說

      asyncPool 這個庫的 ES7 和 ES6 的具體實(shí)現(xiàn)中,我們都使用到了 Promise.allPromise.race 函數(shù)。其中手寫 Promise.all 是一道常見的面試題。剛好趁著這個機(jī)會,阿寶哥跟大家一起來手寫簡易版的 Promise.allPromise.race 函數(shù)。

      3.1 手寫 Promise.all

      Promise.all(iterable) 方法會返回一個 promise 對象,當(dāng)輸入的所有 promise 對象的狀態(tài)都變成 resolved 時,返回的 promise 對象就會以數(shù)組的形式,返回每個 promise 對象 resolve 后的結(jié)果。當(dāng)輸入的任何一個 promise 對象狀態(tài)變成 rejected 時,則返回的 promise 對象會 reject 對應(yīng)的錯誤信息。

      Promise.all = function (iterators) {   return new Promise((resolve, reject) => {     if (!iterators || iterators.length === 0) {       resolve([]);     } else {       let count = 0; // 計數(shù)器,用于判斷所有任務(wù)是否執(zhí)行完成       let result = []; // 結(jié)果數(shù)組       for (let i = 0; i < iterators.length; i++) {         // 考慮到iterators[i]可能是普通對象,則統(tǒng)一包裝為Promise對象         Promise.resolve(iterators[i]).then(           (data) => {             result[i] = data; // 按順序保存對應(yīng)的結(jié)果             // 當(dāng)所有任務(wù)都執(zhí)行完成后,再統(tǒng)一返回結(jié)果             if (++count === iterators.length) {               resolve(result);             }           },           (err) => {             reject(err); // 任何一個Promise對象執(zhí)行失敗,則調(diào)用reject()方法             return;           }         );       }     }   }); };

      需要注意的是對于 Promise.all 的標(biāo)準(zhǔn)實(shí)現(xiàn)來說,它的參數(shù)是一個可迭代對象,比如 Array、String 或 Set 等。

      3.2 手寫 Promise.race

      Promise.race(iterable) 方法會返回一個 promise 對象,一旦迭代器中的某個 promise 對象 resolvedrejected,返回的 promise 對象就會 resolve 或 reject 相應(yīng)的值。

      Promise.race = function (iterators) {   return new Promise((resolve, reject) => {     for (const iter of iterators) {       Promise.resolve(iter)         .then((res) => {           resolve(res);         })         .catch((e) => {           reject(e);         });     }   }); };

      本文阿寶哥帶大家詳細(xì)分析了 async-pool 異步任務(wù)并發(fā)控制的具體實(shí)現(xiàn),同時為了讓大家能夠更好地理解 async-pool 的核心代碼。最后阿寶哥還帶大家一起手寫簡易版的 Promise.allPromise.race 函數(shù)。其實(shí)除了 Promise.all 函數(shù)之外,還存在另一個函數(shù) —— Promise.allSettled,該函數(shù)用于解決 Promise.all 存在的問題,感興趣的小伙伴可以自行研究一下。

      四、參考資源

      • Github – async-pool
      • MDN – Promise.all
      • MDN – Promise.race
      • MDN – Promise.allSettled

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號