ホームページ ウェブフロントエンド jsチュートリアル Nodejs 非同期プログラミングの詳細な説明_node.js

Nodejs 非同期プログラミングの詳細な説明_node.js

May 16, 2016 pm 04:29 PM
nodejs 非同期プログラミング

現在の要件には多数の非同期操作が含まれており、実際のページはますます単一ページ アプリケーションに傾いています。将来的には、backbone、angular、knockout などのフレームワークを使用する可能性がありますが、最初に直面する必要があるのは非同期プログラミングに関する問題です。ノードの台頭により、非同期プログラミングが非常にホットなトピックになっています。一定期間の学習と実践の後、非同期プログラミングの詳細がいくつかまとめられます。

1. 非同期プログラミングの分類

非同期の問題を解決する方法には、一般に、ダイレクト コールバック、パブリッシュ/サブスクライブ モード (イベント モード)、非同期ライブラリ制御ライブラリ (async、when など)、Promise、ジェネレーターなどが含まれます。
1.1 コールバック関数

コールバック関数は、非同期の問題を解決するためによく使用されるメソッドであり、よく参照され、理解しやすく、ライブラリや関数に実装するのが非常に簡単です。これは、非同期プログラミングを使用するときに誰もがよく使用する方法でもあります。

しかし、コールバック関数メソッドには次の問題があります:

1. 邪悪な入れ子ピラミッドを形成する可能性があり、コードが読みにくくなります。

2. 対応できるコールバック関数は 1 つだけですが、これは多くのシナリオで制限となります。

1.2 パブ/サブモード (イベント)

このモードはイベント モードとも呼ばれ、コールバック関数のイベント化であり、jQuery などのライブラリで非常に一般的です。

イベント発行サブスクライバー モデル自体には同期呼び出しと非同期呼び出しの問題はありませんが、ノードでは、エミット呼び出しはイベント ループと非同期でトリガーされることがほとんどです。このモードは、ビジネス ロジックを分離するためによく使用されます。イベント発行者は、登録されたコールバック関数を意識する必要がなく、メッセージを通じてデータを柔軟に転送できます。

このモードの利点は次のとおりです: 1. 理解しやすい; 2. 1 つのコールバック関数に限定されなくなりました。

欠点: 1. クラス ライブラリを使用する必要がある; 2. イベントとコールバック関数の順序が非常に重要

コードをコピーします コードは次のとおりです:
var img = document.querySelect(#id);
img.addEventListener('load', function() {
// 画像の読み込みが完了しました

});
img.addEventListener('error', function() {
// 問題が発生しました
……
});

上記のコードには 2 つの問題があります:

a. img は実際にはロードされており、ロード コールバック関数はこの時点でのみバインドされているため、コールバックは実行されませんが、対応するコールバック関数が実行されることを期待します。

コードをコピーします コードは次のとおりです:
var img = document.querySelect(#id);
関数load() {
...
}
if(img.complete) {
ロード();
} else {
img.addEventListener('load',load);
}
img.addEventListener('error', function() {
// 問題が発生しました
……
});

b. 例外をうまく処理できない

結論: イベント メカニズムは、同じオブジェクトで繰り返し発生する処理に最適です。コールバック関数がバインドされる前にイベントの発生を考慮する必要はありません。

1.3 非同期制御ライブラリ

現在の非同期ライブラリには主に Q、when.js、win.js、RSVP.js などが含まれます。

これらのライブラリの特徴は、コードが直線的であり、自然な習慣に沿って上から下に記述できることです。

欠点は、スタイルが異なるため読みにくくなり、学習コストが増加することです。

1.4 約束

Promise は中国語に訳すと約束となりますが、私の個人的な理解では、非同期完了後に外部の結果 (成功または失敗) を与え、その結果が変わらないことを約束します。言い換えれば、Promise は操作の最終的な戻り値を反映します (Promise は、操作の 1 回の完了から返される最終的な値を表します)。現在、Promise は ES6 仕様に導入されており、Chrome や Firefox などの先進的なブラウザはこのネイティブ メソッドを内部的に実装しているため、非常に使いやすくなっています。

Promise の特徴を次の側面から分析してみましょう:

1.4.1 ステータス

保留、履行、および拒否の 3 つの状態が含まれます。3 つの状態の間で発生できる遷移は 2 つだけ (保留中 ---> 履行、保留中 --> 拒否)、状態遷移は 1 回だけ発生します。

1.4.2 メソッド

then メソッドは、非同期イベントの完了後のコールバック関数を指定するために使用されます。

このメソッドは、Promise を魔法に満ちたものにする、Promise の魂のメソッドと言えます。以下に示すような具体的な症状がいくつかあります:

a) then メソッドは Promise を返します。これにより、複数の非同期操作のシリアル操作が可能になります。

上の図の黄色の丸 1 の値の処理については、Promise のより複雑な部分であり、値の処理は Promise オブジェクトと非 Promise オブジェクトの 2 つの状況に分かれています。

value が Promise 型でない場合は、2 番目の Promise のリゾルブのパラメータ値として value を使用するだけで、Promise 型の場合は、promise2 のステータスとパラメータは完全に value によって決定されると考えることができます。 promsie2 は完全に value の操り人形であり、promise2 は異なる非同期のものを接続する単なるブリッジです。

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

Promise.prototype.then = function(onFulfilled, onRejected) {
    return new Promise(function(resolve, respect) { //此处的Promise标注はpromise2
        ハンドル({
            onFulfilled: onFulfilled、
            onRejected: onRejected,
            解決: 解決、
            拒否: 拒否
        })
    });
}
関数ハンドル(遅延) {
    var handleFn;
    if(状態 === '満たされた') {
        handleFn = deferred.onFulfilled;
    } else if(state === '拒否') {
        handleFn = deferred.onRejected;
    }
    var ret = handleFn(値);
    deferred.resolve(ret);                           //注意、今回の解決策はpromise2の解決策です
}
function resolve(val) {
    if(val && typeof val.then === '関数') {
        val.then(解決);                           // val が promise オブジェクトまたは promise オブジェクトの場合、promise2 の状態は val によって完全に決定されます
        戻る;
    }
    if(callback) { // コールバックは指定された回调関数
        コールバック(val);
    }
}

b) 複数の異なるブロック間の変換が実行されます。

异步中に呼び出し可能なオブジェクトが存在します。これは、then メソッドを持つオブジェクトを意味します。ただ 1 つのオブジェクトが then メソッドを持ち、それに対して実行できるオブジェクトを指します。例:

复制代 代码如下:

var deferred = $('aa.ajax');      // !!deferred.then === true
var P = Promise.resolve(deferred);
p.then(……)

1.4.3 commonJS Promise/A规范

現在、Promise の規定に関しては Promise/A および Promise/A の規定が存在しており、これは Promise の実現が複雑であることを示しています。

复制代 代码如下:
then(fulfilledHandler、rejectedHandler、progressHandler)

1.4.4 注意事项

Promise の 1 つの戻り関数は値を共有しており、結果処理で値がパラメータとして渡される対応する戻り関数です。値がオブジェクトの場合、簡単に変更できる値は無視されます。

var p = Promise.resolve({x: 1});
p.then(function(val) {
    console.log('最初のコールバック: ' val.x );
});
p.then(function(val) {
    console.log('2 番目のコールバック: ' val.x)
})
// 最初のコールバック: 1
// 2 番目のコールバック: 2

1.5 ジェネレーター

上記のメソッドはすべて、非同期操作を完了するためのコールバック関数に基づいています。これらはコールバック関数のカプセル化にすぎません。ジェネレーターは ES6 で提案されており、非同期操作を解決する方法が追加され、コールバック関数に依存しなくなります。

Generator の最大の特徴は、関数を一時停止および再開できることです。この機能は、非同期操作を解決するのに非常に役立ちます。 Generator の一時停止と Promise の例外処理を組み合わせると、非同期プログラミングの問題をよりエレガントに解決できます。特定の実装リファレンス: Kyle Simpson

2. 非同期プログラミングの問題

2.1 例外処理

a) 非同期イベントには、非同期リクエストの発行と結果処理の 2 つのリンクが含まれます。これらの 2 つのリンクは、イベント ループを通じて接続されます。 Try catch を使用して例外をキャプチャする場合は、例外を個別にキャプチャする必要があります。

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

{
を試してください asyncEvent(コールバック); } キャッチ(エラー) {

}

上記のコードはコールバックで例外をキャプチャできませんが、リクエスト プロセスでのみ例外を取得できます。これにより問題が発生します。リクエストの発行とリクエストの処理が 2 人で完了した場合、例外を処理するときに問題が発生しますか?

b) Promise は例外配信を実装します。これによりいくつかの利点がもたらされ、コードが実際のプロジェクトでブロックされないことが保証されます。ただし、非同期イベントが多数ある場合、どの非同期イベントが例外を引き起こしたかを見つけるのは簡単ではありません。

コードをコピーします コードは次のとおりです:
// シナリオの説明: CRM に競合情報を含む価格アラーム情報を表示します。ただし、競合情報の取得には時間がかかります。クエリの遅延を避けるために、バックエンドはレコードを 2 つの部分に分割し、別々に取得します。
// ステップ 1: 競合情報に加えて、価格アラーム情報を取得します
function getPriceAlarmData() {
新しい Promise(function(resolve) を返す {
Y.io(url, {
メソッド: 'get',
データ: params,
on: function() {
成功: function(id, data) {
解決(アラームデータ);
}
}
});
});
}
// アラーム情報取得後、大会情報を取得
getPriceAlarmData().then(function(data) {
//データレンダリング(競技情報を除く)
レンダリング(データ);
新しい Promise(function(resolve) を返す {
Y.io(url, {
メソッド: 'get',
データ: {alarmList: data},
on: function() {
成功: function(id, compData) {
resolve(compData);
}
}
});
});
}) // すべてのデータを取得したら、競合情報をレンダリングします
.then(関数(データ) {
// コンテスト情報をレンダリングします
レンダリング(データ)
}、関数(エラー) {
//例外処理
console.log(err);
});

上記のコードは次のように変換できます:

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

試してみてください{
// 競技以外のアラーム情報を取得
var アラームデータ = アラームデータ例外比較();
render(alarmData);
// アラーム情報に基づいて競合情報を問い合わせます
var CompareData = getCompareInfo(alarmData);
render(compareData);
} キャッチ(エラー) {
console.log(err.message);
}

上記の例では、例外処理が最後に配置されているため、特定のリンクで例外が発生した場合、どのイベントが原因であるかを正確に知ることができません。

2.2 jQuery.Deferred の問題

非同期操作は jQuery にも実装されていますが、この実装は主に次の点で Promise/A 仕様に準拠していません。

a. パラメータの数: 標準 Promise は 1 つのパラメータのみを受け入れることができますが、jQuery は複数のパラメータを渡すことができます

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

関数 asyncInJQuery() {
var d = new $.Deferred();
setTimeout(function() {
d.resolve(1, 2);
}, 100);
d.promise()
を返します }
asyncInJQuery().then(function(val1, val2) {
console.log('出力: ', val1, val2);
});
// 出力: 1 2

b. 結果処理での例外の処理

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

関数 asyncInPromise() {
新しい Promise(function(resolve) を返す {
setTimeout(function() {
var jsonStr = '{"name": "mt}';
solve(jsonStr);
}, 100);
});
}
asyncInPromise().then(function(val) {
var d = JSON.parse(val);
console.log(d.name);
}).then(null, function(err) {
console.log('エラーを表示: ' err.message);
});
// エラーを表示: 入力の予期しない終了
関数 asyncInJQuery() {
var d = new $.Deferred();
setTimeout(function() {
var jsonStr = '{"name": "mt}';
d.resolve(jsonStr);
}, 100);
d.promise()
を返します }
asyncInJQuery().then(function(val) {
var d = JSON.parse(val);
console.log(d.name);
}).then(function(v) {
console.log('success: ', v.name);
}、関数(エラー){
console.log('エラーを表示: ' err.message);
});
//キャッチされない SyntaxError: 入力の予期しない終了

このことから、Promise はコールバック関数の結果処理を実行し、コールバック関数の実行中に例外をキャプチャできるが、jQuery.Deferred はできないことがわかります。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Nodejs はバックエンド フレームワークですか? Nodejs はバックエンド フレームワークですか? Apr 21, 2024 am 05:09 AM

Node.js は、高いパフォーマンス、スケーラビリティ、クロスプラットフォーム サポート、豊富なエコシステム、開発の容易さなどの機能を備えているため、バックエンド フレームワークとして使用できます。

Nodejs インストール ディレクトリ内の npm ファイルと npm.cmd ファイルの違いは何ですか? Nodejs インストール ディレクトリ内の npm ファイルと npm.cmd ファイルの違いは何ですか? Apr 21, 2024 am 05:18 AM

Node.js インストール ディレクトリには、npm と npm.cmd という 2 つの npm 関連ファイルがあります。違いは次のとおりです。拡張子が異なります。npm は実行可能ファイルで、npm.cmd はコマンド ウィンドウのショートカットです。 Windows ユーザー: npm.cmd はコマンド プロンプトから使用できますが、npm はコマンド ラインからのみ実行できます。互換性: npm.cmd は Windows システムに固有ですが、npm はクロスプラットフォームで使用できます。使用上の推奨事項: Windows ユーザーは npm.cmd を使用し、他のオペレーティング システムは npm を使用します。

Nodejsをmysqlデータベースに接続する方法 Nodejsをmysqlデータベースに接続する方法 Apr 21, 2024 am 06:13 AM

MySQL データベースに接続するには、次の手順に従う必要があります。 mysql2 ドライバーをインストールします。 mysql2.createConnection() を使用して、ホスト アドレス、ポート、ユーザー名、パスワード、データベース名を含む接続オブジェクトを作成します。 connection.query() を使用してクエリを実行します。最後に connection.end() を使用して接続を終了します。

C++ 関数を使用して非同期プログラミングを実装するにはどうすればよいですか? C++ 関数を使用して非同期プログラミングを実装するにはどうすればよいですか? Apr 27, 2024 pm 09:09 PM

概要: C++ の非同期プログラミングを使用すると、時間のかかる操作を待たずにマルチタスクを行うことができます。関数ポインターを使用して、関数へのポインターを作成します。コールバック関数は、非同期操作が完了すると呼び出されます。 boost::asio などのライブラリは、非同期プログラミングのサポートを提供します。実際のケースでは、関数ポインターと boost::asio を使用して非同期ネットワーク リクエストを実装する方法を示します。

Nodejs はバックエンド開発言語ですか? Nodejs はバックエンド開発言語ですか? Apr 21, 2024 am 05:09 AM

はい、Node.js はバックエンド開発言語です。これは、サーバー側のビジネス ロジックの処理、データベース接続の管理、API の提供などのバックエンド開発に使用されます。

NodejsとJavaの間に大きな違いはありますか? NodejsとJavaの間に大きな違いはありますか? Apr 21, 2024 am 06:12 AM

Node.js と Java の主な違いは、設計と機能です。 イベント駆動型とスレッド駆動型: Node.js はイベント駆動型で、Java はスレッド駆動型です。シングルスレッドとマルチスレッド: Node.js はシングルスレッドのイベント ループを使用し、Java はマルチスレッド アーキテクチャを使用します。ランタイム環境: Node.js は V8 JavaScript エンジン上で実行され、Java は JVM 上で実行されます。構文: Node.js は JavaScript 構文を使用し、Java は Java 構文を使用します。目的: Node.js は I/O 集中型のタスクに適しており、Java は大規模なエンタープライズ アプリケーションに適しています。

golang フレームワークは同時実行性と非同期プログラミングをどのように処理しますか? golang フレームワークは同時実行性と非同期プログラミングをどのように処理しますか? Jun 02, 2024 pm 07:49 PM

Go フレームワークは Go の同時実行性と非同期機能を使用して、同時タスクと非同期タスクを効率的に処理するためのメカニズムを提供します。 1. 同時実行性は Goroutine によって実現され、複数のタスクを同時に実行できます。 2. 非同期プログラミングはチャネルを通じて実装されます。メインスレッドをブロックせずに実行可能。 3. HTTP リクエストの同時処理、データベース データの非同期取得などの実用的なシナリオに適しています。

Nodejs はどのようなプロジェクトに適していますか? Nodejs はどのようなプロジェクトに適していますか? Apr 21, 2024 am 05:45 AM

Node.js は、次のプロジェクト タイプに適しています。 ネットワークおよびサーバー アプリケーション イベント駆動型アプリケーション リアルタイム アプリケーション データ集約型アプリケーション コマンドライン ツールとスクリプト 軽量マイクロサービス

See all articles