ホームページ ウェブフロントエンド jsチュートリアル JavaScript_javascript テクニックにおけるループ ステートメントの最適化テクニックに関する詳細な説明

JavaScript_javascript テクニックにおけるループ ステートメントの最適化テクニックに関する詳細な説明

May 16, 2016 pm 04:45 PM
javascript

ループは、すべてのプログラミング言語で最も重要なメカニズムの 1 つです。実用的な意味を持つほとんどすべてのコンピューター プログラム (並べ替え、クエリなど) にはループが含まれません。 ループはプログラムの最適化において非常に厄介な部分でもあり、プログラムの複雑さを常に最適化する必要があることがよくありますが、ループがあるため、時間の複雑さと空間の複雑さの選択に悩まされます。

JavaScript には、for () {}、while () {}、do {} while () の 3 種類のネイティブ ループがあり、その中で最もよく使用されるのは for () {} です。

ただし、for は、JavaScript エンジニアがプログラムを最適化するときに最も簡単に無視するタイプのループです。

まずはforの基礎知識を復習しましょう。
JavaScript の for 構文は C 言語から継承されています。for ループの基本構文を使用するには 2 つの方法があります。

1. ループ配列

for ループの基本構文

コードをコピー コードは次のとおりです。

for ( /* Initialization*/2 / * 判定条件 */2 /* ループ処理*/ ) {
//... ロジックコード
}

サンプルコードを使用して詳しく説明します。

コードをコピー コードは次のとおりです:

var array = [1, 2, 3 , 4, 5];
var sum = 0;

for (var i = 0, len = array.length; i < len; i) {
sum = array[i];
}

console.log('配列の項目の合計は %d.', sum);
//=> 配列の項目の合計は 15 です。

このコードでは、まず、累算する項目と合計整数変数を格納する配列を定義して初期化します。 次に、ループを開始します。 for ループの初期化コードでは、i (カウンター) と len (ループ配列の長さのエイリアス) という 2 つの変数も定義して初期化しました。i が len より小さい場合、ループ条件が確立され、ロジック コードが実行されます。ロジックが実行されるたびに、コードが実行されると、i が 1 ずつ増加します。

ループ ロジック コードでは、現在のループ配列項目を sum 変数に追加します。
このサイクルは次のようなフローチャートで表されます:

JavaScript_javascript テクニックにおけるループ ステートメントの最適化テクニックに関する詳細な説明

このフローチャートから、プログラム内の実際のループ本体には、ロジック コードだけでなく、ループ自体を実装するための実行判定やループ処理も含まれていることが簡単にわかります。 。
このように、最適化の考え方が明確になり、4つの側面から最適化することができます。

1. ループ本体前の初期化コード
2. ループ本体内の実行判定条件
3. ロジックコード
4. ロジックコード以降の処理コード

追記: 最初のポイントと 2 番目のポイントの間には重要な関係があります。


1.1 初期化コードと実行判定条件の最適化

まず、誰もがよく知っているコードの一部を見てみましょう。

コードをコピー コードは次のとおりです:

// 間違っています!
for ( var i = 02 i < list.length2 i) {
//... ロジック コード
}

JavaScript を作成するほとんどのエンジニアは、この一見普通のループ方法を今でも使用していると思います。しかし、なぜ私はそれが間違っているとここで言うのでしょうか?
このループ内のすべてを分解して見てみましょう:

1. 初期化コード - このループはカウンター変数の定義と初期化のみを行います。
2. 実行判定条件 - カウンタがリストの長さ未満の場合に true。
3. コードの処理 - カウンターが 1 増加します。

上のフローチャートをもう一度見直してください。何か間違っている点はありませんか?
実際のループ本体には、ロジック コードだけでなく、ループ自体を実装するための実行判定および処理コードも含まれます。 つまり、各ループの前に判定条件 i < list.length を実行する必要があります。 JavaScript では、オブジェクトのプロパティまたはメソッドを読み取るときにクエリが必要です。
何か理解できたようですね?この判定条件には 2 つの操作があります: 1. list 配列から length 属性を問い合わせる 2. i と list.length のサイズを比較する。
リスト配列の要素数がn個だとすると、プログラムはこのループの実行判定で2n回の演算を行う必要があります。

コードを次のように変更すると、

コードをコピー コードは次のとおりです。

// まあ
for (var) i = 0 , len = list.length; i
//...
}

この改善されたコードでは、ループ本体が実行される前に、初期化コードで定義を追加し、len 変数を初期化しました。これは list.length の値を格納するために使用されます (変数、式、ポインター、および値について)。内容については後半で説明します)。 これにより、ループ本体の実行判定でリスト配列の属性を再度問い合わせる必要がなくなり、演算回数が半分で済みます。

上記の手順でアルゴリズムの時間計算量を改善しましたが、空間計算量を引き続き最適化したい場合は、どうすればよいでしょうか? ロジック コードがループ順序によって制限されていない場合は、次の最適化方法を試すことができます。

コードをコピー コードは次のとおりです。

for (var i = list.length - 1; i >= 0; --i) {
//...
}

このコードはループの順序を逆にし、最後の要素インデックス (list.length - 1) から i カウンターを開始し、順方向にループします。 ループおよび実行判定に必要な変数の数を1つに減らすため、変数のクエリ数が減り、CPU命令実行までの時間が削減されます。

1.2 ロジックコードの最適化

ループでは、何らかの操作を実行したり使用したりするために、ループの現在の配列要素を自然に取得します。これにより、必然的に要素への複数の呼び出しが発生します。

コードをコピー コードは次のとおりです。

var array = [
{ name : 'ウィル・ウェン・ガン'、タイプ: 'hentai' },
{ 名前: 'ヴィル・リン'、タイプ: 'moegril' }
];

for (var i = array.length - 1; i >= 0; --i) {
console.log('Name: %s', array[i].name);
console.log('彼/彼女は a(n) %s', array[i].type);

console.log('rn');
}
/*=>
名前: Vill Lin
彼/彼女はモーグリルです

名前: ウィル・ウェン・ガン
彼/彼女は変態です
*/

このコードでは、プログラムは各配列要素の名前と型属性をクエリする必要があります。 配列に n 個の要素がある場合、プログラムは 4n 回のオブジェクト検索を実行します。

コードをコピーします コードは次のとおりです:

1. 2. 配列 [i].name
3. 配列 [i]
4. 配列 [i].type

この時点で、現在の配列要素の値を変数に代入し、それをロジック コードで使用するという解決策を思いついたはずです。

コードをコピー コードは次のとおりです。
var array = [
{ name : 'ウィル・ウェン・ガン'、タイプ: 'hentai' },
{ 名前: 'ヴィル・リン'、タイプ: 'moegril' }
];
var person = null;

for (var i = array.length - 1; i >= 0 && (person = array[i]); --i) {

console.log('名前: %s', person. name);
console.log('彼/彼女は a(n) %s', person.type);

console.log('rn');

}
person = null;

これはかなり美しく見えます。


コードをコピー コードは次のとおりです。
1. array[i] => var person
2. person.name
3. person.type

これは emcascript5 の foreach に少し似ていますが、この 2 つには大きな違いがあるため、ここでは説明しません。

ps: 修正していただきありがとうございます。実験の結果、配列内の要素が直接値転送によって定義されている場合、ループで取得される値はポインタではなく値でなければならないことがわかりました。 したがって、式を定義するか変数を定義するかに関係なく、追加のメモリ領域が必要になります。

1.3 最適化された処理コード

実際には、ループ本体の処理コードで最適化できる部分はあまりなく、i カウンタが 1 増加するだけで十分です。

ps: 何か良い提案や方法があれば、提供してください。 :)

2. ループオブジェクト(オブジェクト)

JavaScript では、for はオブジェクトのプロパティとメソッドをトラバースすることもできます。 for ループは、オブジェクトが属するパッケージング タイプや、コンストラクター内のプロトタイプのプロパティとメソッド (プロトタイプ) をトラバースできないことに注意してください。

構文は配列をループするよりも簡単です。

コードをコピー コードは次のとおりです:
for (/* 初期化*/ var key in object) {
//... ロジックコード
}

私たちはオブジェクトを操作するためにこのメソッドをよく使用します。

コードをコピー コードは次のとおりです:

var person = {
'name ' : 'ウィル・ウェン・ガン',
'タイプ' : '変態',
'スキル' : ['プログラミング'、'写真'、'スピーキング'、'etc']
};

for (個人の var key) {
value = person[key];

// 値が配列の場合、文字列に変換します
if (value instanceof Array) {
value = value.join(', ');
}

console.log('%s: %s', key, value);
}
/*=>
名前: ウィル・ウェン・ガン
タイプ: エロアニメ
スキル: プログラミング、写真、スピーキングなど
*/

mongodb を使用したことがある場合は、そのクエリ メカニズムについてよくご存じでしょう。 mongodb のクエリ メカニズムはその API の魂のようなものであるため、柔軟な curd 操作方法により mongodb は多くの人気と開発の勢いを獲得しました。

nanodb の mongo API 実装では、クエリ実装でループ オブジェクトが広範囲に使用されます。

コードをコピー コードは次のとおりです。

var myDB = nano.db('myDB ');
var myColl = myDB.collection('myColl');

var _cursor = myColl.find({
タイプ : 'repo',
言語 : 'JavaScript'
});

_cursor
.sort({
star: 1
})
.toArray(function(err, rows) {
if (err)
return console.error(えー);

console.log(rows);
});

最適化する必要があるのは、ループ自体ではなく、通過する必要があるオブジェクトの最適化です。
例えば、nanodb の nanocollection クラスは、表面的には配列のように見えますが、すべての要素、つまりオブジェクトを格納し、要素の ID をキーとして要素を格納します。

しかし、これは当てはまりません。これまでにアンダースコアを使用したことのある生徒は、_.invert メソッドを知っているはずです。 これは、渡されたオブジェクトのキーと値を逆にする、かなり興味深いメソッドです。

コードをコピー コードは次のとおりです:

var person = {
'name ' : 'ウィル・ウェン・ガン',
'type' : 'hentai'
};

var _inverted = _.invert(person);
console.log(_inverted);
/*=>
{
'ウィル・ウェン・ガン' : '名前',
'hentai' : 'type'
}
*/

ループ オブジェクトを使用してオブジェクトの一部のプロパティの値をクエリする必要がある場合は、次の方法を試すことができます。

コードをコピー コードは次のとおりです:

var person = {
'name ' : 'ウィル・ウェン・ガン',
'type' : 'hentai'
};

var name = 'ウィル・ウェン・ガン';

var _inverted = _.invert(人);

if (_inverted[name] === 'name') {
console.log('キャッチ!');
}
//=> キャッチ!

ただし、for オブジェクト クエリを使用して最適化できることはあまりありません。すべては実際のニーズに基づいている必要があります。 :p

次に、他の 2 つのループ、while () {} と do {} while () を見てみましょう。 コンピューター サイエンスのコースを受講したことのある人なら、これら 2 つのサイクルについてよく知っていると思います。それらの唯一の違いは、ループ本体が実行される論理順序です。

while () {} の実行シーケンスは for () {} と同様ですが、実行判定はロジック コードの前にありますが、初期化および処理コードは省略されています。
条件が与えられると、その条件が真でなくなるまでロジック コードが実行されます。

コードをコピーします コードは次のとおりです:

var sum = 0;

while (sum sum = sum 1;
}

console.log(sum);
//=> 15

do {} while () は、ロジック コードの後に​​実行判断を置きます。つまり、「最初にカットして後で再生する」ということです。

コードをコピー コードは次のとおりです:

変数合計 = 0;

do {
sum = sum 1;
} while (sum

console.log(sum);
//=> 15

while () {} と do {} while () もカウンタを必要としませんが、特定の条件を使用してロジック コードを実行するか実行を継続するかを決定します。

3. while () {} と do {} while ()

while () {} と do {} while () は主にビジネス ロジックで使用され、タスク キューなどの特定の目的を達成するために一連の操作を継続的に実行します。

しかし、これら 2 種類のループは、デフォルトでは実行条件によってのみ制御されるため、ロジック コードが実行判定に影響を与えない場合、無限ループが発生するため危険です。

コードをコピーします コードは次のとおりです:

var sum = 02

// 警告!
while (sum sum = 1 12
}

このようなコードは while (true) {} に等しいため、使用する前に実行条件と実行条件にどのような影響を与えるかを明確にする必要があります。

4. ループ制御ステートメントを上手に活用する

JavaScript エンジニアなら誰もが Break ステートメントを使用したことがあると思いますが、Continue ステートメントは比較的まれに使用されます。 実際、Continue は多くの優れた JavaScript オープンソース プロジェクトで見つかります。

Continue ステートメントの機能をより深く理解するために、まずコード例を見てみましょう

コードをコピー コードは次のとおりです:

// Node.js Broadcast Server
var net = require('net');
var util = require('util');

varBroadcastServer = net.createServer();

// クライアント ストア
broadcastServer.clients = [];

// Clients Broadcast Method
net.Socket.prototype.broadcast = function(msg) {
var client = BroadcastingServer.clients;
// コレクションでブロードキャストを公開するクライアントを取得 Standard
varindex = client.indexOf(this);

for (var i = client.length - 1; i >= 0; --i) {
if (i === Index) {
// クライアントがブロードキャストし、現在のループを終了します
continue;
}

currClient = クライアント[i];

if (!currClient.destroyed) {
currClient.write(
util.format(
) 'r[Echo Client %s:%d] %snInput: ',
currClient.リモートアドレス、currClient.remotePort、msg)
);
}
}
};

// 新しいクライアントが接続されました
broadcastServer.on('connection', function(client) {
BroadcastingServer.clients.push(client);

// ようこそ
client.write('[ブロードキャスト サーバー] ようこそ!nInput:');
client.broadcast(client, '参加しました!');

// メッセージハンドル
client.on('data', function(msg) {
client.broadcast(msg);
client.write('rInput:');
} );

// ハンドルを切断します
client.on('end', function() {
client.broadcast('Left!');
})
});

// Bind
broadcastServer.listen(8080, function() {
console.log('ブロードキャストサーバーがバインドされています。');
});

このコードは、node.js の net モジュールに基づいてブロードキャスト サーバーを実装します。ブロードキャスト メソッドでは、ブロードキャスト クライアントを発行するクライアントを除くすべての確立された接続に情報を配布します。

コードの内容は非常に単純です。クライアントが他のクライアントにブロードキャストを公開する必要がある場合、そのクライアントに対応するクライアント オブジェクトのブロードキャスト メソッドが呼び出されます。ブロードキャスト メソッドでは、プログラムはまずキャッシュを取得します。クライアント ソケット コレクション内の現在のクライアントの位置インデックスを取得し、ループ内のすべてのクライアント ソケットをパブリッシュします。ループ カウンタが以前に取得した位置インデックスに達すると、現在のループ本体のロジック コードがスキップされ、次のループが続行されます。 。

C/C 言語を勉強したことのあるエンジニアは、「goto 文を使用しないでください」というアドバイスをさまざまな場所から受け取ると思います。

この「悪名高い」goto ステートメントは、実際にはコード フロー コントローラーです。ここでは goto ステートメントの詳細については説明しません。 ただし、JavaScript には明らかな goto ステートメントはありませんが、break ステートメントと continue ステートメントから、JavaScript における goto の影を見つけるのは難しくありません。

これは、break ステートメントと continue ステートメントにより、コード ジャンプ用に定義されたラベル名を受け入れることができるためです。

mdn が提供するサンプルコードを見てみましょう。


コードをコピー コードは次のとおりです:
var i, j;
loop1:

for (i = 0; i loop2:
for (j = 0; j if (i == 1 && j == 1) {
continue loop1;
console.log ("i = " i ", j = " j);
}
}
}

// 出力は次のとおりです:

// "i = 0, j = 0"

// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// "i = 2, j = 0"
// "i = 2, j = 1"
// "i = 2, j = 2"
// "i = 1, j = 1" と "i = 1, j = 2"


の両方をスキップすることに注目してください。

このコード例では、2 つのレベルのループが実装されており、Continue ステートメントへの後続の呼び出しのためにループの各レベルの外側にラベルが定義されています。

最初のループはloop1のラベルにあります。つまり、以降のプログラムでは、 continue文やbreak文でloop1のラベルが選択されていれば、一番外側のループが飛び出すことになります。

第 2 レベルのループは、最上位ループのループ 2 のラベル内にあり、 continue ステートメントまたは Break ステートメントでループ 2 ラベルが選択されている場合、最上位ループのループ本体に戻ります。


ループ制御文を使用することで、本来のループ実行判定に干渉することができ、非常に複雑な論理システムを構築することができます。 余談ですが、Linux カーネルには goto ステートメントがたくさんあります。なぜ今でも goto ステートメントを使用しないでくださいという意見をよく聞きます。グーグルで調べてください。

5. 高度なループ

5.1 アンロールループ

まず 2 つのコードを見て、どちらのパフォーマンスが優れているかを考えてみましょう。

コードをコピー コードは次のとおりです:

// Setup
var array = [
["DATA", "DATA", "DATA", "DATA", "DATA", "DATA", "DATA", "DATA ", "データ", "データ", "データ", "データ"],
["データ", "データ", "データ", "データ", "データ", "データ", "データ" , "データ", "データ", "データ", "データ", "データ"],
["データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ"],
["データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ"],
["データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ"],
["データ", "データ", "データ", "データ" , "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ"],
["データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ", "データ"],
["データ", "データ", " DATA", "DATA", "DATA", "DATA", "DATA", "DATA", "DATA", "DATA", "DATA", "DATA"]
];
関数処理( item) {
// item
} で何かを実行します

// Case 1
for (var i = array.length - 1; i >= 0; i--) {
for (var j = array[i].length - 1; j >= 0; i--) {
process(array[i][j]);
}
}

// ケース 2
for (var i = array.length - 1; i >= 0; i = i - 4) {
for (var j = array[i].length - 1 ; j >= 0; j = j - 6) {
プロセス(配列[i][j]);
プロセス(配列[i][j - 1]);
プロセス(配列) [i][j - 2]);
process(array[i][j - 3]);
process(array[i][j - 4]);
process(array[i] ][j - 5]);
}
for (var j = array[i - 1].length - 1; j >= 0; j = j - 6) {
process(array [i][j]);
process(array[i][j - 1]);
process(array[i][j - 2]);
process(array[i][ j - 3]);
process(array[i][j - 4]);
process(array[i][j - 5]);
}
for (var j = array[i - 2].length - 1; j >= 0; j = j - 6) {
process(array[i][j]);
process(array[i][j - 1]);
プロセス(配列[i][j - 2]);
プロセス(配列[i][j - 3]);
プロセス(配列[i][j - 4] );
process(array[i][j - 5]);
}
for (var j = array[i - 3].length - 1; j >= 0; j = j - 6) {
プロセス(array[i][j]);
プロセス(array[i][j - 1]);
process(array[i][j - 2]);
プロセス(配列[i][j - 3]);
プロセス(配列[i][j - 4]);
プロセス(配列[i][j - 5]);
}
}


私は配列内のすべての子数グループの要素を実行する必要があります。解決策は、ケース 2 のパフォーマンスが優れていることです。これは、各 6 つの要素間の実行判断がすべて省略されており、自然に比べて常に高速であるためです。 ここでは、さらに強力な解決策を検討します。あるトラフィック サイクルで大規模なデータ コレクションの継続処理が必要な場合、データ コレクションの開始時からデータ量が変更されることはないので、その採用を検討することもできます。 1 つは duff 装置と呼ばれるテクニックです。このテクニックは、開発者である Tom duff の名前で命名され、最初に c の言葉で実現されました。その後、jeff greenberg が javascript に移植し、andrew b を経由しました。 。


代打代打以下:
//クレジット: サイトの高速化 (New Riders、2003)
var iterations = Math.floor(values.length / 8);
var leftover = value.length % 8;
var i = 0;
if (leftover > 0) {

do {
process(values[i ]);
} while (--leftover > 0);
}
do {
process(values[i ]);
process(values[i ]);
process(values[i ]);
process(values[i ]);
process(values [i ]);
process(values[i ]);
process(values[i ]);
process(values[i ]);
} while (--iterations > 0 );

このテクニックの原理は、必要な次の数を得るために値の長さを 8 よりも小さくして計算し、math.floor() 関数で結果が整数であることを保証し、その後 8 整数までに計算できない数を再計算することです。

これらの要素は個別に処理され、8 回は 1 回の展開回数として実行されます。

私たちはこのデバイスをさらにパッケージ化して、強烈な風味を持つ API を取得できるようにしました。

复制代码代码如下:

function duff(array, マッパー) {
var n = Math.floor(array.length / 8);
var l = array.length % 8;

var i = 0;
if (l > 0) {
do {
マッパー(array[i ]);
} while (--i > 0);
}
do {
マッパー(配列[i]);
マッパー(配列[i]);
マッパー(配列[i]);
マッパー(配列[i] );
マッパー(配列[i]);
マッパー(配列[i]);
マッパー(配列[i]);
マッパー(配列[i]);
} while (--n > 0);
}

duff([...], function(item) {
//...
});

ここでは、上記の 3 つの反復ソリューションの一連のパフォーマンス テストと結果を示します。 http://jsperf.com/spreaded-loop

5.2 非ネイティブループ

どのプログラミング言語でも、ループはその言語が提供するネイティブ ループ ステートメントを通じてだけでなく、他のメソッドを通じて間接的に実装することもできます。

最初に高校数学の内容、つまり数列の一般式を復習しましょう。

コードをコピー コードは次のとおりです。

bacause
a[1] = 1
a[n] = 2 * a[n - 1] 1

so
a [n] 1 = 2 * a [n -1] 2 [n -1] 1)= 2

then

a[n] 1 = (a[n] 1) / (a[n - 1] 1) * (a[n - 1] 1) / (a[n - 2] 1) * ... * (a[2] 1) / (a[1] 1) * (a[i] 1)

a[n] 1 = 2 * 2 * ... * 2 * 2
a[n] 1 = 2^n
a[n] = 2^n - 1

最終

a[n] = 2^n - 1



上記の簡単な計算を読んで、これから説明する内容を推測できたかもしれません。 はい、再帰を使用してループを実装することもできます。

再帰は、数学とコンピューターサイエンスにおいて非常に重要な応用方法です。これは、関数が使用されるときにそれ自体を呼び出すことを意味します。

node.js コミュニティでは、再帰は非常に重要なテクノロジであるミドルウェア テクノロジを実装するために使用されます。 これは、まだリリースされていない新しいバージョンの webjs のミドルウェア実装コードの一部です。


コードをコピー コードは次のとおりです:

/**
* ミドルウェア実行メソッド
* @param {String} url 現在のリクエスト url
* @param {Object} はリクエスト オブジェクトを要求します
* @param {Object} は応答オブジェクトです
* @param {関数} out 完全なコールバック
* @return {関数} サーバー
 */
server.runMiddlewares = function(url, req, res, out) {
varindex = -1;

var middlewares = this._usingMiddlewares;

// 次のミドルウェアが存在する場合は実行します
function next(err) {
index ;

// 現在のミドルウェア
var curr = middlewares[index];

if (curr) {
var check = new RegExp(curr.route);

// ルートを確認します
if (check.test(url)) {
try {
function Later() {
debug('ミドルウェアは、後で実行する必要があると言っています % s', url);
// 現時点では依存関係はありません
if (middlewares.indexOf(curr) !== middlewares.length - 1) {
_later(curr);
インデックス--;
next();
} else {
debug('ミドルウェアの依存関係が間違っています');

// このミドルウェアは実行できません
out();
}
}

// ミドルウェアを実行します
if (utils.isFunc(curr.handler)) {

// 通常のミドルウェア関数
curr.handler(req, res, next, Later);

} else if (utils.isObject(curr.handler) && utils.isFunc(curr.handler.emit)) {

// サーバー オブジェクト
curr.handler.emit('request', req, res, next, Later);

} else {

// ミドルウェアに問題があります
next();

}
} catch(err) {
next();
}
} else {
next();
}
} else {
// パイプラインの次のステップに進みます
out();
}
}

// ミドルウェアが他のミドルウェアに依存している場合、
// 後で実行できるようにすることができます
function _later(curr) {
var i = middlewares.indexOf(curr);
var _tmp1 = middlewares.slice(0, i);
_tmp1.push(middlewares[i 1], curr);
var _tmp2 = middlewares.slice(i 2);
[].push. apply(_tmp1, _tmp2);
ミドルウェア = _tmp1;
}

// 最初のミドルウェア
next();

これを返します;
};

は、このセグメントのコードを確認した上で、その正確な確認を行った後ではなく、多数のコードを削除します。 >代幣如下:


server.runMiddlewares = function(url, req, res, out) {
varindex = -1;

var middlewares = this._usingMiddlewares;

// 次のミドルウェアが存在する場合は実行します
function next(err) {
Index ;

// 現在のミドルウェア
var curr = middlewares[index];

if (curr) {
var check = new RegExp(curr.route);

// ルートを確認します
if (check.test(url)) {
// 現在のミドルウェアを実行します
curr.handler(req, res, next);
} else {
next();
}
} else {
// パイプラインの次のステップに進みます
out();
}
}

// 最初のミドルウェア
next();

これを返します;
};

ミドルウェア システムの実装で再帰が使用できる理由は、node.js の非同期 I/O に対するプログラム フローの応答方法として再帰が最適であるためです。

このミドルウェア実装コードでは、this._usingmiddlewaresがループ配列、関数next()がループ本体、check.test(url)が実行判定条件、ループ処理コードがループ本体の先頭となります。インデックス カウンターが 1 ずつインクリメントされ、次の関数自体が再帰的に呼び出されます。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

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

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

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

WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

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

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

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

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

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

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

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

JavaScript で HTTP ステータス コードを簡単に取得する方法 JavaScript で HTTP ステータス コードを簡単に取得する方法 Jan 05, 2024 pm 01:37 PM

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

JavaScriptでinsertBeforeを使用する方法 JavaScriptでinsertBeforeを使用する方法 Nov 24, 2023 am 11:56 AM

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

See all articles