序文プログラムを作成するときに、読み込みの進行状況やアップロードの進行状況など、進行状況を表示する必要に迫られることがよくあります。 質問私は WebGL アプリケーションを作成しており、アプリケーションのプリロード フェーズ中にロードの進行状況を計算する必要があります。 +-------------------------------------------------------------+ | | | リソース | | | | +----------+ +-----------------+ +-----------------+ | | | スクリプト1 | | モデル1 | | モデル2 | | | +----------+ | | | | | | | -------------+ | | -------------+ | | | +----------+ | |model1.json | | | |model2.json | | | | | スクリプト2 | | +-------------+ | | +-------------+ | | | +----------+ | | | | | | | +-------------+ | | +-------------+ | | | +----------+ | | 素材1 | | | | 素材1 | | | | | テクスチャ1 | | | +--------+ | | | | +--------+ | | | | +----------+ | | |テクスチャ1| | | | | |テクスチャ1| | | | | | | +--------+ | | | | +--------+ | | | | +----------+ | | +--------+ | | | | +--------+ | | | | | テクスチャ2 | | | |テクスチャ2| | | | | |テクスチャ2| | | | | +----------+ | | +--------+ | | | | +--------+ | | | | | +-------------+ | | +-------------+ | | | | | | | | | | +-------------+ | | +-------------+ | | | | | マテリアル2 | | | | マテリアル2 | | | | | +-------------+ | | +-------------+ | | | +-----------------+ +-----------------+ | | | +-------------------------------------------------------------+ ここで前提となるのは、リソースをロードするときに、ロードが完了したと見なされる前に、リソースとそれが参照するリソースがすべてロードされていることを確認する必要があるということです。 クラスアセット{ ロード(onProgress) { 新しいPromise((resolve) => {を返す if (typeof onProgress !== 'function') { onProgress = (_p) => { }; } loadedCount = 0 とします。 let totalCount = 10; // 注意: デモ用です onLoaded = () => { ロードされたカウント++; onProgress(読み込まれたカウント / 合計継続時間); 読み込まれたカウントが合計カウントの場合、解決します。 }; 約束.すべて( this.refAssets.map(asset => asset.load().then(onLoaded)) ); }); } } このインターフェースができたので、loadedCount と totalCount のグローバルメンテナンスという形式を引き続き使用すると、扱いが非常に面倒になります。 原理基本的な考え方は分割統治です。大きなタスクを複数の小さなタスクに分割し、すべての小さなタスクの進行状況を個別に計算し、最後にすべての小さなタスクの進行状況を結合して全体の進行状況を取得します。 +--------------------------------------------------------------------+ | | | | | 総進捗状況 | | | | +---------+----------+-----------+----------+---------+---------+ | | | スクリプト1 | スクリプト2 | テクスチャ1 | テクスチャ2 | モデル1 | モデル2 | | | | (0~1) | (0~1) | (0~1) | (0~1) | (0~1) | (0~1) | | | +---------+----------+-----------+----------+---------+---------+ | | | | モデル1 | | +-------------+------------------------+-----------+ | | | model1.json | マテリアル1 | マテリアル2 | | | | (0~1) | (0~1) | (0~1) | | | +------------------------+------------------------+ | | | テクスチャ1 | テクスチャ2 | | | | (0~1) | (0~1) | | | +----------+-------------+ | | | | モデル2 | | +-------------+------------------------+-----------+ | | | model2.json | マテリアル1 | マテリアル2 | | | | (0~1) | (0~1) | (0~1) | | | +------------------------+------------------------+ | | | テクスチャ1 | テクスチャ2 | | | | (0~1) | (0~1) | | | +----------+-------------+ | | | +--------------------------------------------------------------------+ この原則に基づいて、すべてのリソースの現在の読み込み進行状況をリストに保存し、onProgress がトリガーされるたびにマージ操作を実行して全体の進行状況を計算することで、進行状況が実装されます。 var 進行 = [ 0, // スクリプト1, 0, // スクリプト2, 0, // テクスチャ1, 0, // テクスチャ2, 0, // モデル1, 0, // モデル2 ]; 関数 onProgress(p) { // TODO: progresses[??] = p; progresses.reduce((a, b) => a + b, 0) / progresses.length を返します。 } しかし、ここには難しさがあります。onProgress コールバックがトリガーされたとき、リスト内のどの項目を更新する必要があるかをどのように知るのでしょうか? var 進捗 = []; 関数add(){ 進行します。push(0); var インデックス = progresses.length - 1; 関数onProgress(p)を返す{ progresses[インデックス] = p; 減らす(); }; } 関数reduce() { progresses.reduce((a, b) => a + b, 0) / progresses.length を返します。 } クロージャを使用してリソースのインデックスを保持します。onProgress がトリガーされると、リスト内の対応する項目の進行状況をインデックスに従って更新できます。正しい進行状況は最終マージ時に計算できます。 テスト次のコードを使用して、読み込みプロセス全体をシミュレートできます。 クラスアセット{ コンストラクター(totalCount) { this.loadedCount = 0; this.totalCount = 合計カウント; this.timerId = -1; } ロード(onProgress) { if (typeof onProgress !== 'function') { onProgress = (_p) => { }; } 新しいPromise((resolve) => {を返す this.timerId = setInterval(() => { this.loadedCount++; onProgress(this.loadedCount / this.totalCount); (this.loadedCount === this.totalCount)の場合{ タイマーIDをクリアします。 解決する(); } }, 1000); }); } } クラス Progress { コンストラクター(onProgress) { onProgress は、次の式で定義されます。 this._list = []; } 追加() { this._list.push(0); 定数インデックス = this._list.length - 1; 戻り値 (p) => { this._list[インデックス] = p; これをreduce()します。 }; } 減らす() { 定数 p = Math.min(1, this._list.reduce((a, b) => a + b, 0) / this._list.length); this.onProgress(p); } } const p = 新しい Progress(console.log); 定数asset1 = 新しいアセット(1); 定数asset2 = 新しいアセット(2); 定数asset3 = 新しいアセット(3); 定数asset4 = 新しいアセット(4); 定数asset5 = 新しいアセット(5); Promise.all([ アセット1.load(p.add())、 アセット2.load(p.add())、 アセット3.load(p.add())、 アセット4.load(p.add())、 アセット5.load(p.add())、 ]).then(() => console.log('すべてのリソースが読み込まれました')); /** 出力 Promise { <state>: "pending" } 0.2 0.3 0.366666666666666664 0.416666666666666663 0.456666666666666667 0.55666666666666668 0.6233333333333333 0.6733333333333333 0.7133333333333333 0.78 0.83000000000000001 0.8699999999999999 0.9199999999999999 0.96 1 すべてのリソースが読み込まれました */ この方法の利点は、loadedCount と totalCount のグローバル管理を回避し、この部分の作業をリソースの内部管理に戻すことができることです。必要なのは、大きなタスクをマージして計算することだけです。 欠点も明らかであり、onProgress インターフェースを統一する必要があります。既存のプロジェクトを進めるのは非常に難しいため、新規プロジェクトや小規模プロジェクトに適しています。 以上がJavaScript進捗管理の詳細です。JavaScript進捗管理の詳細については、123WORDPRESS.COMの他の関連記事にも注目してください! 以下もご興味があるかもしれません:
|
<<: Windows 10 での MySQL 5.7.21 winx64 のインストールと設定方法のグラフィック チュートリアル
MySQLに何がインストールされているか確認する rpm -qa | grep -i mysql n...
01. コンパイルオプションとカーネルコンパイルLinux カーネル (英語: linux kern...
プロットレビュー前回の記事では、ロケーション命令の解析プロセスを分析しました。この内容を簡単に確認し...
async_hooks モジュールは、Node.js バージョン 8.0.0 に正式に追加された実験...
オリジナル: http://developer.yahoo.com/performance/rule...
この記事では、例を使用して MySQL ビューの管理ビュー操作について説明します。ご参考までに、詳細...
目次sambaをアンインストールしてインストールする新しい共有パスを作成し、権限を設定するSamba...
目次物体オブジェクト定義オブジェクトのメンバーを反復処理するJS組み込みオブジェクト数学オブジェクト...
目次1. ハッシュテーブルの原理2. ハッシュテーブルの概念3. ハッシュ競合問題1. チェーンアド...
序文継続的なコード配信のプロセスで、Jenkins を利用して Docker イメージを作成すると、...
目次リストレンダリングキーの原理と機能主要原則の分析キーの役割要約するリストレンダリングキーの原理と...
構造擬似クラスセレクタの紹介構造擬似クラスセレクターは、いくつかの特殊効果を処理するために使用されま...
目次序文参考比較手動比較浅い比較徹底比較要約する序文JavaScript でプリミティブ値を比較する...
MySQL バージョン 5.0 ではストアド プロシージャのサポートが開始されました。ストアド プロ...
他のデバイスの画像をローカルディレクトリにマウントするなど、サーバー上の静的リソースにアクセスする必...