亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

淺談Node異步編程的機制

2019-11-19 15:08:51
字體:
來源:轉載
供稿:網友

本文介紹了Node異步編程,分享給大家,具體如下:

目前的異步編程主要解決方案有:

  • 事件發布/訂閱模式
  • Promise/Deferred模式
  • 流程控制庫

事件發布/訂閱模式

Node自身提供了events模塊,可以輕松實現事件的發布/訂閱

//訂閱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)將這個限制去掉

繼承events模塊

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';//重新定義為已準備狀態    })  }}

多異步之間的協作方案

以上情況事件與偵聽器的關系都是一對多的,但在異步編程中,也會出現事件與偵聽器多對一的情況。

這里以渲染頁面所需要的模板讀取、數據讀取和本地化資源讀取為例簡要介紹一下

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)})

偏函數方案

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)})

引入EventProxy模塊方案

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);})

Promise/Deferred模式

以上使用事件的方式時,執行流程都需要被預先設定,這是發布/訂閱模式的運行機制所決定的。

$.get('/api',{  success:onSuccess,  err:onError,  complete:onComplete})//需要嚴謹設置目標

那么是否有一種先執行異步調用,延遲傳遞處理的方式的?接下來要說的就是針對這種情況的方式:Promise/Deferred模式

Promise/A

Promise/A提議對單個異步操作做出了這樣的抽象定義:

  • Promise操作只會處在三種狀態的一種:未完成態,完成態和失敗態。
  • Promise的狀態只會出現從未完成態向完成態或失敗態轉化,不能逆反,完成態和失敗態不能相互轉化
  • Promise的狀態一旦轉化,就不能被更改。

一個Promise對象只要具備then()即可

  • 接受完成態、錯誤態的回調方法
  • 可選地支持progress事件回調作為第三個方法
  • then()方法只接受function對象,其余對象將被忽略
  • then()方法繼續返回Promise對象,以實現鏈式調用

通過Node的events模塊來模擬一個Promise的實現

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;}

以上通過then()將回調函數存放起來,接下來就是等待success、error、progress事件被觸發,實現這個功能的對象稱為Deferred對象,即延遲對象。

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)}

因此,可以對一個典型的響應對象進行封裝

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

轉換成

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

要完成上面的轉換,首先需要對res對象進行封裝,對data,end,error等事件進行promisify

var promisify = function(res){  var deferred = new Deferred(); //創建一個延遲對象來在res的異步完成回調中發布相關事件  var result = ''; //用來在progress中持續接收數據  res.on('data',function(chunk){ //res的異步操作,回調中發布事件    result += chunk;    deferred.progress(chunk);  })  res.on('end',function(){        deferred.resolve(result);  })  res.on('error',function(err){    deferred.reject(err);  });  return deferred.promise   //返回deferred.promise,讓外界不能改變deferred的狀態,只能讓promise的then()方法去接收外界來偵聽相關事件。}promisify(res).then(function(){  //done},function(err){  //error},function(chunk){  console.log('Body:' + chunk);})

以上,它將業務中不可變的部分封裝在了Deferred中,將可變的部分交給了Promise

Promise中的多異步協作

Deferred.prototype.all = function(promises){  var count = promises.length; //記錄傳進的promise的個數  var that = this; //保存調用all的對象  var results = [];//存放所有promise完成的結果  promises.forEach(function(promise,i){//對promises逐個進行調用    promise.then(function(data){//每個promise成功之后,存放結果到result中,count--,直到所有promise被處理完了,才出發deferred的resolve方法,發布事件,傳遞結果出去      count--;      result[i] = data;      if(count === 0){        that.resolve(results);      }    },function(err){      that.reject(err);    });  });  return this.promise; //返回promise來讓外界偵聽這個deferred發布的事件。}var promise1 = readFile('foo.txt','utf-8');//這里的文件讀取已經經過promise化var promise2 = readFile('bar.txt','utf-8');var deferred = new Deferred();deferred.all([promise1,promise2]).thne(function(results){//promise1和promise2的then方法在deferred內部的all方法所調用,用于同步所有的promise  //TODO},function(err){  //TODO})

支持序列執行的Promise

嘗試改造一下代碼以實現鏈式調用

var Deferred = function(){  this.promise = new Promise()}//完成態Deferred.prototype.resolve = function(obj){  var promise = this.promise;  var handler;  while((handler = promise.queue.shift())){    if(handler && handler.fulfilled){      var ret = handler.fulfilled(obj);      if(ret && ret.isPromise){        ret.queue = promise.queue;        this.promise = ret;        return;      }    }  }}//失敗態Deferred.prototype.reject = function(err){  var promise = this.promise;  var handler;  while((handler = promise.queue.shift())){    if(handler && handler.error){      var ret = handler.error(err);      if(ret && ret.isPromise){        ret.queue = promise.queue;        this.promise = ret;        return      }    }  }}//生成回調函數Deferred.prototype.callback = function(){  var that = this;  return function(err,file){    if(err){      return that.reject(err);    }    that.resolve(file)  }}var Promise = function(){  this.queue = []; //隊列用于存儲待執行的回到函數  this.isPromise = true;};Promise.prototype.then = function(fulfilledHandler,errorHandler,progressHandler){  var handler = {};  if(typeof fulfilledHandler === 'function'){    handler.fulfilled = fulfilledHandler;  }  if(typeof errorHandler === 'function'){    handler.error = errorHandler;  }  this.queue.push(handler);  return this;}var readFile1 = function(file,encoding){  var deferred = new Deferred();  fs.readFile(file,encoding,deferred.callback());  return deferred.promise;}var readFile2 = function(file,encoding){  var deferred = new Deferred();  fs.readFile(file,encoding,deferred.callback());  return deferred.promise;}readFile1('file1.txt','utf8').then(function(file1){  return readFile2(file1.trim(),'utf8')}).then(function(file2){  console.log(file2)})

流程控制庫另外進行總結

參考《深入淺出node.js》一書,想學學習可以下載電子書,下載地址://www.49028c.com/books/481114.html

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人免费在线视频| 综合网中文字幕| 日韩av在线网页| 国产精品一区二区三区久久久| 欧美福利在线观看| 国产精品男人的天堂| 亚洲天堂一区二区三区| 午夜精品久久久久久久99黑人| 中文字幕成人在线| 18一19gay欧美视频网站| 日韩欧美主播在线| 中文字幕精品久久| 26uuu久久噜噜噜噜| 揄拍成人国产精品视频| 亚洲国产精品资源| 538国产精品视频一区二区| 亚洲午夜av电影| 成人精品久久av网站| 久久久免费精品视频| 亚洲视频综合网| 国产99久久精品一区二区 夜夜躁日日躁| 亚洲国产成人91精品| 亚洲一区二区三区香蕉| 亚洲综合自拍一区| 亚洲欧美国产一区二区三区| 日韩在线播放视频| www.日本久久久久com.| 国产美女精品免费电影| 国产精品免费一区豆花| 在线一区二区日韩| 欧美日韩亚洲一区二区三区| 日韩成人在线网站| 一本色道久久88综合亚洲精品ⅰ| 国产精品自产拍在线观看中文| 欧美激情一区二区久久久| 亚洲香蕉在线观看| 在线性视频日韩欧美| 欧美亚洲激情视频| 国产在线视频欧美| 日韩一区二区久久久| 69久久夜色精品国产69| 久久综合久久美利坚合众国| 亚洲精品电影网在线观看| 6080yy精品一区二区三区| 日韩极品精品视频免费观看| 久久综合伊人77777蜜臀| 国产精品国产亚洲伊人久久| 欧美大片在线看| 欧美成人午夜激情在线| 久久久影视精品| 久青草国产97香蕉在线视频| 国产精品成人av性教育| 国产精品99久久久久久久久久久久| 国产精品久久电影观看| 中文字幕日韩专区| 日本精品一区二区三区在线播放视频| 国产成人亚洲综合91| 国产亚洲精品美女久久久| 欧美日韩在线一区| 日韩欧美精品免费在线| 国产精品入口夜色视频大尺度| 日韩中文字幕精品| 色噜噜狠狠色综合网图区| 亚洲精品白浆高清久久久久久| 国内精品久久久久影院优| 日韩中文字幕在线看| 国产一区二区动漫| 成人激情av在线| 欧美一乱一性一交一视频| 国产亚洲aⅴaaaaaa毛片| 欧美美最猛性xxxxxx| 欧美日韩免费区域视频在线观看| 91国产美女在线观看| 在线一区二区日韩| 日本国产高清不卡| 亚洲男人的天堂在线| 成人av在线网址| 日本高清+成人网在线观看| 欧美激情视频网址| 亚洲人成电影网站色xx| 亚洲护士老师的毛茸茸最新章节| 亚洲欧洲午夜一线一品| 精品久久久久久久中文字幕| 国产亚洲美女久久| 91麻豆国产精品| 国产91在线播放| 久久久伊人欧美| 精品亚洲永久免费精品| 九九热r在线视频精品| 久久久精品日本| 欧美色道久久88综合亚洲精品| 国产福利视频一区二区| 欧美性理论片在线观看片免费| 久久久国产在线视频| 色综合老司机第九色激情| 中文日韩在线视频| 日韩av在线最新| 中文字幕亚洲综合久久| 91精品国产自产在线老师啪| 亚洲国产精品99| 欧美一区二区三区艳史| 欧美中文在线观看| 亚洲人成伊人成综合网久久久| 国产免费一区二区三区香蕉精| 91av在线不卡| 亚洲黄色www网站| 欧美午夜视频在线观看| 亚洲国产成人精品一区二区| 菠萝蜜影院一区二区免费| 亚洲成人精品视频| 日韩视频永久免费观看| 亚洲最大av网| 日韩av不卡电影| 亚洲石原莉奈一区二区在线观看| 久久亚洲精品毛片| 国产精品一区二区三区毛片淫片| 日韩美女视频中文字幕| 成人久久久久爱| 热久久免费视频精品| 国内精品久久影院| 久久精品电影网站| 日韩在线观看免费全集电视剧网站| 国产精品久久久久久久久久久久| 伊是香蕉大人久久| 久久久伊人欧美| 日韩在线视频免费观看| 欧美性极品少妇精品网站| 亚洲片在线观看| 国产日韩av在线播放| 欧美精品免费在线观看| 亚洲色图综合网| 久久成人综合视频| 欧美最猛性xxxxx亚洲精品| 亚洲精品国精品久久99热一| 欧美丝袜一区二区三区| 欧美性videos高清精品| 亚洲精品美女在线观看| 亚洲精品国产成人| 国产精品丝袜久久久久久不卡| 麻豆乱码国产一区二区三区| 久久综合久久美利坚合众国| 国产精品一区二区三区免费视频| 欧美成人精品h版在线观看| 亚洲成人在线网| 亚洲国产精品99| 两个人的视频www国产精品| 国产欧美一区二区三区久久| 亚洲国产一区二区三区在线观看| 国产精品香蕉在线观看| 国产精品久久久久久久久久久久久| 精品国产999| 最近2019中文免费高清视频观看www99| 国产成人一区三区| 亚洲视频在线免费观看| 成人免费午夜电影| xxav国产精品美女主播| 18久久久久久| 97涩涩爰在线观看亚洲| 欧美午夜片在线免费观看| 日韩av在线网站| 欧美日韩国产成人在线观看| 国产激情999| 精品国产91乱高清在线观看| 热re99久久精品国产66热|