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

Node非同期プログラミング機構の詳細説明

小云云
小云云オリジナル
2018-01-09 17:17:371339ブラウズ

この記事では主に Node 非同期プログラミングの仕組みを紹介します。編集者がそれを紹介し、参考にさせていただきます。編集者をフォローして見てみましょう。皆さんのお役に立てれば幸いです。

この記事では、Node 非同期プログラミングを紹介し、それを皆さんと共有します。詳細は次のとおりです。

非同期プログラミングの現在の主なソリューションは次のとおりです:

  • イベント パブリッシング/サブスクリプション モード

  • Promise/Deferred モード

  • プロセス制御ライブラリ

イベント発行/購読モード

ノード自体がイベントモジュールを提供し、イベントの発行/購読を簡単に実装できます


//订阅
emmiter.on("event1",function(message){
  console.log(message);
})
//发布
emmiter.emit("event1","I am mesaage!");

リスナーは柔軟に追加および削除でき、イベントと特定の処理ロジックを簡単に関連付けて分離できます

イベント パブリッシュ/サブスクライブ モデルは、ビジネス ロジックを分離するためによく使用されます。イベント発行者は、サブスクライブされたリスナーがビジネス ロジックを実装する方法や、リスナーの数に注意を払う必要はありません。リスナーが存在し、メッセージを通じて柔軟にデータを転送できます。

次の HTTP は典型的なアプリケーション シナリオです


var req = http.request(options,function(res){
  res.on('data',function(chunk){
    console.log('Body:'+ chunk);
  })
  res.on('end',function(){
    //TODO
  })
})

10 を超えるリスナーがイベントに追加される場合は、emmite.setMaxListeners(0) を呼び出すことで警告が表示されます

。イベントモジュールを継承します


var events = require('events');
function Stream(){
  events.EventEmiiter.call(this);
}
util.inherits(Stream,events.EventEmitter);

イベントキューを使用して雪崩問題を解決します

いわゆる雪崩問題とは、アクセス量が多く同時実行数が多い条件下でのキャッシュ障害です。多くのリクエストが同時にデータベースに統合されると、データベースは同時にこのような大規模なクエリリクエストに耐えることができなくなり、ウェブサイト全体の応答速度にさらに影響を及ぼします。 解決策:


var proxy = new events.EventEmitter();
var status = "ready"; 
var seletc = function(callback){
  proxy.once("selected",callback);//为每次请求订阅这个查询时间,推入事件回调函数队列
  if(status === 'ready'){ 
    status = 'pending';//设置状态为进行中以防止引起多次查询操作
    db.select("SQL",function(results){
      proxy.emit("selected",results); //查询操作完成后发布时间
      status = 'ready';//重新定义为已准备状态
    })
  }
}


複数の非同期イベント間の解決策

上記の状況は、リスナー間の関係は 1 対多ですが、非同期プログラミングでは、イベントとリスナーの間に多対 1 の状況も存在する可能性があります。

ここでは、ページのレンダリングに必要なテンプレートの読み取り、データの読み取り、およびローカライズされたリソースの読み取りを例として取り上げ、EventProxy モジュール ソリューションを簡単に紹介します

var count = 0 ;
var results = {};
var done = function(key,value){
  result[key] = value;
  count++;
  if(count === 3){
    render(results);
  }
}
fs.readFile(template_path,"utf8",function(err,template){
  done('template',template)
})
db.query(sql,function(err,data){
  done('data',data);
})
l10n.get(function(err,resources){
  done('resources',resources)
})

Promise/Deferred モード

でイベントを使用する場合上記の方法では、実行プロセスを事前に設定する必要があります。これは、パブリッシュ/サブスクライブ モードの動作メカニズムによって決定されます。


var after = function(times,callback){
  var count = 0, result = {};
  return function(key,value){
    results[key] = value;
    count++;
    if(count === times){
      callback(results);
    }
  }
}
var done = after(times,render);
var emitter = new events.Emitter();
emitter.on('done',done);  //一个侦听器
emitter.on('done',other);  //如果业务增长,可以完成多对多的方案

fs.readFile(template_path,"utf8",function(err,template){
  emitter.emit('done','template',template);
})
db.query(sql,function(err,data){
  emitter.emit('done','data',data);
})
l10n.get(function(err,resources){
  emitter.emit('done','resources',resources)
})

では、非同期呼び出しを先に実行して配信処理を遅らせる方法はあるのでしょうか?次に説明するのは、この状況に対処する方法です。 Promise/Deferred パターン

Promise/A


Promise/A は、単一の非同期操作に対して次のような抽象的な定義を提案します。

Promise 操作は、未完了、完了、失敗の 3 つの状態のいずれかのみ。


Promiseの状態は、未完了状態から完了状態または失敗状態にのみ変換され、完了状態と失敗状態を相互に変換することはできません

。 Promise は変換されますが、変更することはできません。

Promise オブジェクトには then() のみが必要です

  • 完了状態とエラー状態でコールバック メソッドを受け入れます

  • オプションで 3 番目のメソッドとして進捗イベント コールバックをサポートします

  • then() メソッドのみ関数オブジェクトを受け入れ、他のオブジェクトは無視されます

then() メソッドはチェーン呼び出しを実現するために Promise オブジェクトを返し続けます

  • Node のイベント モジュールを通じて Promise 実装をシミュレートします

  • var proxy = new EventProxy();
    proxy.all('template','data','resources',function(template,data,resources){
      //TODO
    })
    fs.readFile(template_path,'utf8',function(err,template){
      proxy.emit('template',template);
    })
    db.query(sql,function(err,data){
      proxy.emit('data',data);
    })
    l10n.get(function(err,resources){
      proxy.emit('resources',resources);
    })

    コールバック関数は保存されますthen() を介して実行され、次のステップでは、success、error、progress イベントがトリガーされるのを待ちます。この関数を実装するオブジェクトは Deferred オブジェクト、つまり遅延オブジェクトと呼ばれます。
  • $.get('/api',{
      success:onSuccess,
      err:onError,
      complete:onComplete
    })
    //需要严谨设置目标
  • したがって、典型的な応答オブジェクトはカプセル化されて
  • var Promise = function(){
      EventEmitter.call(this)
    }
    util.inherits(Promise,EventEmitter);
    
    Promise.prototype.then = function(fulfilledHandler,errHandler,progeressHandler){
      if(typeof fulfilledHandler === 'function'){
        this.once('success',fulfilledHandler); //实现监听对应事件
      }
      if(typeof errorHandler === 'function'){
        this.once('error',errorHandler)
      }
      if(typeof progressHandler === 'function'){
        this.on('progress',progressHandler);
      }
      return this;
    }
に変換され、上記の変換を完了するには、まずresオブジェクト、data、end、Errorをカプセル化する必要があります。その他のイベントは promisify


var Deferred = function(){
  this.state = 'unfulfilled';
  this.promise = new Promise();
}
Deferred.prototype.resolve = function(obj){ //当异步完成后可将resolve作为回调函数,触发相关事件
  this.state = 'fulfilled';
  this.promise.emit('success',obj);
}
Deferred.prototype.reject = function(err){
  this.state = 'failed';
  this.promise.emit('error',err);
}
Deferred.prototype.progress = function(data){
  this.promise.emit('progress',data)
}

上記はビジネスの不変部分を Deferred でカプセル化し、可変部分を Promise に引き渡します

Promise での複数の非同期コラボレーション

res.setEncoding('utf8');
res.on('data',function(chunk){
  console.log("Body:" + chunk);
})
res.on('end',function(){
  //done
})
res.on('error',function(err){
  //error
}

シーケンスをサポートする Promise実行

チェーン呼び出しを実装するようにコードを変換してみます

res.then(function(){
  //done
},function(err){
  //error
},function(chunk){
  console.log('Body:' + chunk);
})

関連する推奨事項:

Javascript での非同期プログラミングの 4 つの方法の紹介

非同期プログラミングの説明 es6 の Promise


詳細JavaScript非同期プログラミングにおけるコールバック関数とマネージャーの使用例の説明

以上がNode非同期プログラミング機構の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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