ホームページ >ウェブフロントエンド >jsチュートリアル >Express開発の歴史
この記事では、Express の非同期進化の歴史を中心に紹介します。非常に優れていると思いますので、参考にしてください。エディターをフォローして一緒に見てみましょう
1. はじめに
JavaScript の世界では、非同期 (JavaScript は単一スレッドで実行されるため、JavaScript の非同期はブロックされる可能性があります) が随所に存在します。
Express は、ノード環境で非常に人気のある Web サーバー フレームワークであり、Node Web アプリケーションの大部分が Express を使用します。
JavaScript を使用してサーバーサイドのコードを記述する場合、必然的に非同期を多用することになります。 JavaScript と Node が進化するにつれて、非同期処理メソッドも進化します。
次に、Express における非同期処理の進化を見てみましょう。
2. JavaScript での非同期処理
非同期の世界では、JavaScript ではどのような方法があるのでしょうか?
2.1. コールバック
コールバックは、JS で最も独創的で最も古い非同期通知メカニズムです。
function asyncFn(callback) { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); callback(); // 发通知 }, 2000); } asyncFn(function () { console.log('我会在2s后输出'); });
2.2. イベントモニタリング
一定時間リッスンして結果を取得する関数です。非同期メソッドが完了すると、通知効果を実現するためにイベントがトリガーされます。
2.3. パブリッシュ/サブスクライブ
非同期完了時にオブザーバー パターンを使用してパブリッシャーを変更します。この時点で、発行者は購読者に変更を通知します。
2.4, Promise
Promiseはコールバック関数の改良版です。これを使用すると、非同期を並列化し、コールバック地獄を回避できます。
function asyncFn() { return new Promise((resolve, reject) => { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); resolve(); // 发通知(是否有感觉到回调的影子?) }, 2000); }); } asyncFn() .then(function () { console.log('我会在2s后输出'); });
2.5、Generator
Generator関数は、ES6によって提供される非同期プログラミングソリューションです。
次のコードは単なるデモです。実際、ジェネレーターの使用プロセスは比較的複雑なので、この記事では説明しません。
function asyncFn() { return new Promise((resolve, reject) => { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); resolve(); // 发通知(是否有感觉到回调的影子?) }, 2000); }); } function* generatorSync() { var result = yield asyncFn(); } var g = generatorSync(); g.next().value.then(()=>{ console.log('我会在2s后输出'); });
2.6、async...await
は現在JavaScriptで非同期を扱うための最良の解決策であると言えます。
function asyncFn() { return new Promise((resolve, reject) => { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); resolve(); // 发通知(是否有感觉到回调的影子?) }, 2000); }); } async function run(){ await asyncFn(); console.log('我会在2s后输出'); } run();
3. Express での非同期処理
Express で一般的に使用されるソリューションは、コールバック関数、Promise、および async...await です。
デモ環境を構築するには、express-generator を通じて Express プロジェクトを初期化します。一般に、サーバー側プロジェクトはルートを使用してビジネス ロジックを呼び出します。したがって、私たちもこの原則に従います:
routs/index.js を開くと、次の内容が表示されます。次のデモでは、このファイルをデモンストレーションに使用します。
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router;
3.1. Expressの非同期ロジックを扱うコールバック関数
Expressではルートが複数のミドルウェアをロードできるため、ミドルウェアの記述方法に従ってビジネスロジックを記述できます。このようにして、非同期ロジックを次の層に非常に簡単に分割できます。
var express = require('express'); var router = express.Router(); function asyncFn(req, res, next) { setTimeout(() => { req.user = {}; // 设置当前请求的用户 next(); }, 2000); } function asyncFn2(req, res, next) { setTimeout(() => { req.auth = {}; // 设置用户权限 next(); }, 2000); } function asyncFn3(req, res, next) { setTimeout(() => { res.locals = { title: 'Express Async Test' }; // 设置数据 res.render('index'); // 响应 }, 2000); } /* GET home page. */ router.get('/', asyncFn, asyncFn2, asyncFn3); // 一步步执行中间件 module.exports = router;
3.2. Promise 処理 Express 非同期ロジック
このソリューションでは、複数のビジネス ロジックが Promise を返す関数にパッケージ化されています。ビジネス メソッドを通じて複合コールを実行して、1 つのインと 1 つのアウトの効果を実現します。
var express = require('express'); var router = express.Router(); function asyncFn(req, res) { return new Promise((resolve, reject) => { setTimeout(() => { req.user = {}; // 设置当前请求的用户 resolve(req); }, 2000); }); } function asyncFn2(req) { return new Promise((resolve, reject) => { setTimeout(() => { req.auth = {}; // 设置用户权限 resolve(); }, 2000); }); } function asyncFn3(res) { return new Promise((resolve, reject) => { setTimeout(() => { res.locals = { title: 'Express Async Test' }; // 设置数据 res.render('index'); // 响应 }, 2000); }); } function doBizAsync(req, res, next) { asyncFn(req) .then(() => asyncFn2(req)) .then(() => asyncFn3(res)) .catch(next); // 统一异常处理 }; /* GET home page. */ router.get('/', doBizAsync); module.exports = router;
3.3. async...await は Express の非同期ロジックを処理します
実際、このソリューションには Promise のサポートも必要ですが、記述方法はより直感的で、エラー処理はより直接的です。
Express は初期のソリューションであり、async...await のグローバル エラー処理がないため、パッケージ化を使用して処理できることに注意してください。
var express = require('express'); var router = express.Router(); function asyncFn(req) { return new Promise((resolve, reject) => { setTimeout(() => { req.user = {}; // 设置当前请求的用户 resolve(req); }, 2000); }); } function asyncFn2(req) { return new Promise((resolve, reject) => { setTimeout(() => { req.auth = {}; // 设置用户权限 resolve(); }, 2000); }); } function asyncFn3(res) { return new Promise((resolve, reject) => { setTimeout(() => { }, 2000); }); } async function doBizAsync(req, res, next) { var result = await asyncFn(req); var result2 = await asyncFn2(req); res.locals = { title: 'Express Async Test' }; // 设置数据 res.render('index'); // 响应 }; const tools = { asyncWrap(fn) { return (req, res, next) => { fn(req, res, next).catch(next); // async...await在Express中的错误处理 } } }; /* GET home page. */ router.get('/', tools.asyncWrap(doBizAsync)); // 需要用工具方法包裹一下 module.exports = router;
4. 概要
ただし、koa はより新しく優れた使用法をサポートしています (koa はジェネレーター、koa2 ネイティブの非同期)。しかし、node 0.x を使い始めた人間として、私は今でも Express に特別な思い入れを持っています。
上記のソリューションの一部はすでに koa で使用されており、Express の巨大なエコシステムと組み合わせることで、さらに強力になります。
この記事のGithubアドレス
以上がExpress開発の歴史の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。