同時実行制御とは何ですか? JavaScript で同時実行制御を実装するにはどうすればよいですか?
日々の開発プロセスでは、同時リクエストの数の制御など、同時実行制御シナリオに遭遇することがあります。では、JavaScript で同時実行制御を実装するにはどうすればよいでしょうか?この質問に答える前に、同時実行制御について簡単に説明しましょう。
実行する To Do タスクが 6 つあり、同時に実行できるタスクの数を制限したいとします。つまり、同時に実行できるタスクは最大 2 つです。 。 実行タスク リストのいずれかのタスクが完了すると、プログラムは自動的にToDoタスク リストから新しいToDoタスクを取得し、そのタスクを実行タスク リストに追加します。 。上記のプロセスを誰もがより直感的に理解できるように、Abago は特別に次の 3 つの絵を描きました:
1.1 Stage 1
1.2 フェーズ 2
1.3 フェーズ 3
# #わかりました、同時実行制御の導入後、アバオ兄弟は Github の async-pool ライブラリを使用して、非同期タスク同時実行制御の具体的な実装を紹介します。
async-pool:https://github.com/rxaviers/async-pool
ネイティブ ES6/ を使用して、制限された同時実行で複数の Promise を返す関数と非同期関数を実行します。 ES7。
2. 同時実行制御の実装
async-pool このライブラリは、ES7 と ES6 の 2 つの異なるバージョンの実装を提供します。具体的な実装については、その使用方法を見てみましょう。
2.1 asyncPool の使用
const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i)); await asyncPool(2, [1000, 5000, 3000, 2000], timeout);
上記のコードでは、このライブラリ asyncPool# によって提供される async-pool を使用します。 ## 非同期タスクの同時実行制御を実装する機能。
asyncPool 関数のシグネチャは次のとおりです:
function asyncPool(poolLimit, array, iteratorFn){ ... }
- ##poolLimit
- (数値型): を表します。制限された同時実行数;
- (配列タイプ): タスク配列を表します;
- (関数タイプ): 反復を表します関数、使用 各タスク項目の処理を実装するために、この関数は Promise オブジェクトまたは非同期関数を返します。
関数を使用した後の、対応する実行プロセスは次のとおりです。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>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]`.</pre><div class="contentsignin">ログイン後にコピー</div></div>
上記のアノテーション情報を観察することで、次のことがわかります。
関数内の制御フローを大まかに理解します。まず、asyncPool
関数の ES7 実装を分析しましょう。
2.2 asyncPool ES7 の実装
async function asyncPool(poolLimit, array, iteratorFn) { const ret = []; // 存储所有的异步任务 const executing = []; // 存储正在执行的异步任务 for (const item of array) { // 调用iteratorFn函数创建异步任务 const p = Promise.resolve().then(() => iteratorFn(item, array)); ret.push(p); // 保存新的异步任务 // 当poolLimit值小于或等于总任务个数时,进行并发控制 if (poolLimit <= array.length) { // 当任务完成后,从正在执行的任务数组中移除已完成的任务 const e = p.then(() => executing.splice(executing.indexOf(e), 1)); executing.push(e); // 保存正在执行的异步任务 if (executing.length >= poolLimit) { await Promise.race(executing); // 等待较快的任务执行完成 } } } return Promise.all(ret); }
上記のコードでは、
Promise.all と Promise.race
の機能が最大限に活用されています。 . ES7 で提供されている async await
機能と組み合わせることで、ついに同時実行制御機能が実現します。ステートメントの await Promise.race(executing);
行を使用すると、実行タスク リスト
内のより高速なタスクが完了するのを待ってから、次のサイクルの実行を続行します。 asyncPool ES7 の実装は比較的シンプルです。次に、
機能を使用せずに同じ機能を実現する方法を見てみましょう。 2.3 asyncPool ES6 実装
function asyncPool(poolLimit, array, iteratorFn) { let i = 0; const ret = []; // 存储所有的异步任务 const executing = []; // 存储正在执行的异步任务 const enqueue = function () { if (i === array.length) { return Promise.resolve(); } const item = array[i++]; // 获取新的任务项 const p = Promise.resolve().then(() => iteratorFn(item, array)); ret.push(p); let r = Promise.resolve(); // 当poolLimit值小于或等于总任务个数时,进行并发控制 if (poolLimit <= array.length) { // 当任务完成后,从正在执行的任务数组中移除已完成的任务 const e = p.then(() => executing.splice(executing.indexOf(e), 1)); executing.push(e); if (executing.length >= poolLimit) { r = Promise.race(executing); } } // 正在执行任务列表 中较快的任务执行完成之后,才会从array数组中获取新的待办任务 return r.then(() => enqueue()); }; return enqueue().then(() => Promise.all(ret)); }
ES6 実装バージョンでは、コア制御ロジックは、内部的にカプセル化された
enqueue 関数を通じて実装されます。 Promise.race(executing)
によって返された Promise
オブジェクトが完了すると、array
Get new から enqueue
関数が呼び出されます。配列からの ToDo タスク。 3. A Bao 兄弟から言いたいことがあります
の ES7 および ES6 の特定の実装では、Promise.all
および Promise.race
関数。その中でも、手書きの Promise.all
は面接でよく聞かれる質問です。この機会を利用して、A Bao 兄弟と皆さんは、Promise.all
関数と Promise.race
関数の簡単なバージョンを手書きするようになりました。 <h4 id="手写-Promise-all">3.1 手写 Promise.all</h4><p><strong><code>Promise.all(iterable)
方法会返回一个 promise 对象,当输入的所有 promise 对象的状态都变成 resolved
时,返回的 promise 对象就会以数组的形式,返回每个 promise 对象 resolve 后的结果。当输入的任何一个 promise 对象状态变成 rejected
时,则返回的 promise 对象会 reject 对应的错误信息。
Promise.all = function (iterators) { return new Promise((resolve, reject) => { if (!iterators || iterators.length === 0) { resolve([]); } else { let count = 0; // 计数器,用于判断所有任务是否执行完成 let result = []; // 结果数组 for (let i = 0; i < iterators.length; i++) { // 考虑到iterators[i]可能是普通对象,则统一包装为Promise对象 Promise.resolve(iterators[i]).then( (data) => { result[i] = data; // 按顺序保存对应的结果 // 当所有任务都执行完成后,再统一返回结果 if (++count === iterators.length) { resolve(result); } }, (err) => { reject(err); // 任何一个Promise对象执行失败,则调用reject()方法 return; } ); } } }); };
需要注意的是对于 Promise.all
的标准实现来说,它的参数是一个可迭代对象,比如 Array、String 或 Set 等。
3.2 手写 Promise.race
Promise.race(iterable)
方法会返回一个 promise 对象,一旦迭代器中的某个 promise 对象 resolved 或 rejected,返回的 promise 对象就会 resolve 或 reject 相应的值。
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); }); } }); };
本文阿宝哥带大家详细分析了 async-pool 异步任务并发控制的具体实现,同时为了让大家能够更好地理解 async-pool 的核心代码。最后阿宝哥还带大家一起手写简易版的 Promise.all
和 Promise.race
函数。其实除了 Promise.all
函数之外,还存在另一个函数 —— Promise.allSettled
,该函数用于解决 Promise.all
存在的问题,感兴趣的小伙伴可以自行研究一下。
四、参考资源
更多编程相关知识,请访问:编程视频!!
以上が同時実行制御とは何ですか? JavaScript で同時実行制御を実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

Java コレクション フレームワークは、スレッドセーフなコレクションと同時実行制御メカニズムを通じて同時実行を管理します。スレッドセーフなコレクション (CopyOnWriteArrayList など) はデータの一貫性を保証しますが、非スレッドセーフなコレクション (ArrayList など) は外部同期を必要とします。 Java は、ロック、アトミック操作、ConcurrentHashMap、CopyOnWriteArrayList などのメカニズムを提供して同時実行性を制御し、それによってマルチスレッド環境でのデータの整合性と一貫性を確保します。

同時プログラミングは、Goroutine と同時実行制御ツール (WaitGroup、Mutex など) を介して Go に実装されており、サードパーティのライブラリ (sync.Pool、sync.semaphore、queue など) を使用してその機能を拡張できます。これらのライブラリは、タスク管理、リソース アクセス制限、コード効率の向上などの同時操作を最適化します。キュー ライブラリを使用してタスクを処理する例では、実際の同時実行シナリオでのサードパーティ ライブラリのアプリケーションを示します。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用
