Rumah > hujung hadapan web > tutorial js > Perbincangan ringkas tentang pattern_node.js pemerhati Nodejs

Perbincangan ringkas tentang pattern_node.js pemerhati Nodejs

WBOY
Lepaskan: 2016-05-16 15:36:49
asal
952 orang telah melayarinya

1 Saya telah menggunakan Nodejs untuk beberapa lama baru-baru ini, saya akan menyemak APInya dan menggunakan lebih banyak ciri baharu untuk mendapatkan tahap penguasaan yang lebih tinggi Ringkasan API ini berbeza daripada versi bahasa Inggeris yang ringkas . Saya akan melakukan lebih banyak pengembangan dan saya harap ia akan membantu semua orang, mari mulakan dengan Acara teras

Peristiwa Nodejs melaksanakan mod pemerhati, yang menyokong mekanisme teras Nodejs, dan http/fs/mongoose, dsb. semuanya mewarisi Peristiwa dan boleh menambah acara mendengar. Corak reka bentuk ini sering digunakan dalam idea pengaturcaraan komponen sisi klien Mari kita fahami secara ringkas corak ini terlebih dahulu.

Kali pertama saya bersentuhan dengan corak pemerhati adalah dalam kod sumber Ext.util.observable rangka kerja Extjs. Saya baru menggunakan js pada masa itu dan merasakan corak ini sangat berkuasa corak reka bentuk pertama yang saya temui Kemudian, ia juga disertakan dalam kod sumber underscore.js. Memandangkan yang kedua adalah lebih ringkas dan lebih elegan, saya pada dasarnya mengikuti idea ini semasa menulis komponen.

Mod pemerhati adalah untuk menambah acara pemantauan pada objek, seperti on('show', callback), yang akan dicetuskan oleh objek apabila ia memenuhi syarat seperti show Penyemak imbas itu sendiri telah melaksanakan pemantauan mekanisme untuk dom.

Jika kita menambah pemantauan keyup untuk input, tujuannya adalah untuk mengeluarkan nilainya

$( 'input' ).on( 'keyup', function(){
   console.log( this.value );
} );
Salin selepas log masuk
Apabila anda memasukkan kandungan dengan cara ini, nilainya akan dikeluarkan dalam log.

Tetapi jika kita membuat komponen seperti Dialog, bagaimana kita boleh memantau acara tunjukkan/sembunyikan yang paling biasa digunakan?

Pendekatan asas adalah untuk mengkonfigurasi panggilan balik secara langsung semasa instantiasi, seperti

var dialog = new Dialog({
  content: '这里是弹出框的内容',
  show: function(){
    console.log( '当弹框时输出此段内容' );
  }
});
Salin selepas log masuk
Ini juga boleh digunakan, tetapi ia jelas tidak cukup fleksibel Bagaimana saya boleh menjadikan dialog seperti input dan boleh menambah acara pada bila-bila masa

2. Pelaksanaan mod pemerhati

Mula-mula laksanakan objek Peristiwa, yang menyediakan pemantauan asas dan pemancaran pencetus disusun dalam _events objek dalam bentuk json

var Events = {
  on: function( name, callback){
    this._events = this._events || {};
    this._events[ name ] = this._events[ name ] || [];
    this._events[ name ].push( callback );
  },
  emit: function( name ){
    this._events = this._events || {};
    var args = Array.prototype.slice.call( arguments, 1 ),
       me = this;
    if( this._events[ name ] ){
      $.each( this._events[ name ], function( k, v ){
        v.call( me, args );
      } )
    }
  }   
}
Salin selepas log masuk
Satu lagi fungsi abstrak digunakan untuk menyalin atribut untuk objek

function extend( source ){
  var args = Array.prototype.slice.call( arguments, 1 );
  for( var i = 0, parent; parent = args[i]; i++ ){
    for( var prop in parent ){
      source[ prop ] = parent[ prop ];
    }
  }
}
Salin selepas log masuk
Laksanakan Dialog,
Melaksanakan penciptaan sahaja; kaedah: tunjukkan / sembunyikan;

Apabila anda melihat kesannya, tambah gaya ini

Melaksanakan komponen
.dialog{
  position: fixed;
  top: 50%;
  left: 50%;
  margin: -50px 0 0 -100px;
  width: 200px;
  height: 120px;
  background: #fff;
  border: 5px solid #afafaf;
}
Salin selepas log masuk

Atribut lanjutan
var Dialog = function( config ){
  this.config = config;
  this.init( this.config );
};
Salin selepas log masuk

Jana tika dan tambahkan tiga rancangan serta sembunyikan acara mendengar padanya
extend( Dialog.prototype, {

  init: function( config ){
    this.render( config )
  },

  render: function( config ){
    this.el = $( '<div>' ).addClass( 'dialog' );
    this.el.html( config.content );
    $( 'body' ).append( this.el );
  },

  show: function( param ){
    this.el.fadeIn();
    this.emit( 'show', param );
  },

  hide: function( param ){
    this.el.fadeOut();
    this.emit( 'hide', param );
  }

}, Events );

Salin selepas log masuk

Kami menambah enam acara pertunjukan berbeza dan menyembunyikan acara dalam enam kali.
var dialog = window.dialog = new Dialog({
  content: 'dialog one'
});

dialog.on( 'show', function( txt ){
  console.log( 'dialog show one ' + txt );
} );

//do something

dialog.on( 'show', function( txt ){
  console.log( 'dialog show two ' + txt );
} );

//do something

dialog.on( 'show', function( txt ){
  console.log( 'dialog show three ' + txt );
} );

//do something

dialog.on( 'hide', function( txt ){
  console.log( 'dialog hide one ' + txt );
} );

//do something

dialog.on( 'hide', function( txt ){
  console.log( 'dialog hide two ' + txt );
} );

//do something

dialog.on( 'hide', function( txt ){
  console.log( 'dialog hide three ' + txt );
} );

Salin selepas log masuk
Apabila dialog.show() dilaksanakan, tiga log yang sepadan akan dikeluarkan. Acara yang ditambahkan disimpan dalam dialog._events, seperti yang ditunjukkan dalam rajah


Tiga rancangan yang ditambahkan semuanya berjaya dikeluarkan dan acara disimpan dalam atribut _eventsPerbincangan ringkas tentang pattern_node.js pemerhati Nodejs

nodejs Events juga melaksanakan proses ini.

3. Struktur

var Events = require( 'events' );
console.log( Events );
/*
输出如下数据,可以看出 Events指向其EventEmiter
{ [Function: EventEmitter]
  EventEmitter: [Circular],
  usingDomains: [Getter/Setter],
  defaultMaxListeners: 10,
  init: [Function],
  listenerCount: [Function] }
*/

var myEmitter = new Events();
console.log( myEmitter );
/*
{ domain: null,
  _events: {},   //可以看到实例本身也有_events属性,添加的监听的事件就保存在这里
  _maxListeners: undefined}
*/

console.log( myEmitter.__proto__ );
/*
{ domain: undefined,
  _events: undefined,
  _maxListeners: undefined,
  setMaxListeners: [Function: setMaxListeners],
  emit: [Function: emit],
  addListener: [Function: addListener],
  on: [Function: addListener],
  once: [Function: once],
  removeListener: [Function: removeListener],
  removeAllListeners: [Function: removeAllListeners],
  listeners: [Function: listeners] }
*/

myEmitter.on( 'show', function( txt ){ console.log( 'one ' + txt )})
myEmitter.on( 'show', function( txt ){ console.log( 'tow ' + txt )})
myEmitter.on( 'hide', function( txt ){ console.log( 'one ' + txt )})
myEmitter.emit( 'show', 'show' );
myEmitter.setMaxListeners( 10 );
console.log( myEmitter );
/*
{ domain: null,
  _events: { show: [ [Function], [Function] ], hide: [Function] }, //添加后的事情,以json形式存放
  _maxListeners: 10 }
*/

Salin selepas log masuk
4. API

Kaedah yang disediakan termasuk pada, yang merupakan singkatan daripada addListener. Mereka semua menambah peristiwa mendengar pada contoh tersebut. Mari kita jelaskan secara ringkas

5
Untuk menggunakan Peristiwa, biasanya hanya buat seketika, seperti yang ditunjukkan dalam bahagian API di atas
property
_events: undefined,   //以压栈形式存放on进来的事件
_maxListeners: undefined  //设置最大监听数,超出提warn

----------------------------------------------------------------------------------------------------------------

method
setMaxListeners: [Function: setMaxListeners], 
/*设置私有属性_maxListeners的值,默认Events会在当某监听事件多于10个时发现警告(见上面Events.defaultMaxListeners),以防止内存泄露,如
(node) warning: possible EventEmitter memory leak detected. 11 show listeners added. Use emitter.setMaxListeners() to increase limit.
但这只是个友好的提醒,可以通过设置最大监听数来规避这个问题
myEmitter.setMaxListeners( 20 );
*/

emit: [Function: emit],
 /*触发监听事件
emitter.emit( event, [arg1], [arg2], ... )
如myEmitter.on( 'show', 'prompt content' );
 参数1为事件名,参数二供on回调里的参数
 */

addListener: [Function: addListener],
 /*
添加监听事件
emitter.addListener( event, listener );
如 myEmitter.addListener( 'show', function( txt ){ console.log( txt ) } );
参数一是事件名,参数二是对应的回调,回调里的参数就是 emit里的arguments.prototype.slice.call(1);
 */

on: [Function: addListener],
 /*
是addListener简写
 */

once: [Function: once],
 /*
作用同 on,不过emit一次后就失效了
emitter.once( event, listener );
如 myEmitter.once( 'show', function( txt ){ console.log( txt ) } );
当myEmitter.emit执行第二次时没有输出
 */

removeListener: [Function: removeListener],
 /*
移除指定事件的指定回调,此时回调不能再用匿名函数。
emitter.removeListener( event, listener );
如 
function show( txt ){ console.log( txt ) };
myEmitter.on( 'show', show );
console.log( myEmitter._events ); 
// { show: [ Function: show ] }
myEmitter.removeListener( 'show', show );  
 console.log( myEmitter._events ); 
// {}
 */

removeAllListeners: [Function: removeAllListeners],
 /*
 删除指定事件的所有回调
 emitter.removeAllListeners( [ event ] );
 如 
  myEmitter.removeAllListeners( 'show' );   //删除所有show监听
  myEmitter.removeAllListeners();   //删除所有监听
 */

listeners: [Function: listeners]
/*
查看指定监听
emitter.listeners( event );
如 myEmitter.listeners( 'show' ); //返回一个数组
同我们前面使用的 myEmitter._events[ 'show' ]
*/

另外Events类本身提供了一个方法
Events.listenerCount( emitter, event ); 获取指定实例下指定监听数
如 Event.listenerCount( myEmitter, 'show' )

-----------------------------------------------------------------------------------------------

还有两个event
newListener / remoteListener,分别应用于为实例添加( on / once )和删除( removeListener ) 操作。
emitter.on( event, listener );
emitter.on( 'newListener', function( event, listener ){
  console.log( emitter.listeners( 'show' ) );   //注意,此时监听还并没有添加到 emitter.listeners
  console.log( arguments );  
 });

 emitter.on( 'removeListener', function(){
  console.log( emitter.listeners( 'show' ) );
  console.log( arguments );
 })

Salin selepas log masuk
Walau bagaimanapun, jika kita turut melaksanakan komponen pada bahagian nodejs, seperti Dialog sebelumnya, bagaimanakah kita boleh menjadikan Dialog juga mempunyai fungsi Peristiwa? Panjangkan penyelesaian yang boleh dilaksanakan dengan Extjs

Buat pembina Dialog

Dengan cara ini, mekanisme Peristiwa dilaksanakan untuk komponen Apabila kaedah dipanggil, acara akan dicetuskan

var Dialog = function(){
  //do something
}

//抽象apply函数,提供属性的深度复制,同上面的extend
function apply( source ){
  var args = Array.prototype.slice.call( arguments, 1 );
  for( var i = 0, parent; parent = args[i]; i++ ){
    for( var prop in parent ){
      source[ prop ] = parent[ prop ];
    }
  }
}

//抽象extend函数,用于实现继承
var extend = function(){
  // inline overrides
  var io = function(o){
    for(var m in o){
      this[m] = o[m];
    }
  };
  var oc = Object.prototype.constructor;

  return function(sb, sp, overrides){
    if(typeof sp == 'object'){
      overrides = sp;
      sp = sb;
      sb = overrides.constructor != oc &#63; overrides.constructor : function(){sp.apply(this, arguments);};
    }
    var F = function(){},
      sbp,
      spp = sp.prototype;

    F.prototype = spp;
    sbp = sb.prototype = new F();
    sbp.constructor=sb;
    sb.superclass=spp;
    if(spp.constructor == oc){
      spp.constructor=sp;
    }
    sb.override = function(o){
      apply(sb, o);
    };
    sbp.superclass = sbp.supr = (function(){
      return spp;
    });
    sbp.override = io;
    apply(sb, overrides);
    sb.extend = function(o){return extend(sb, o);};
    return sb;
  };
}();

//将Events属性继承给Dialog
Dialog = extend( Dialog, Events );

//为Dialog新增 method show,其内触发 event show
Dialog.prototype.show = function( txt ){
  this.emit( 'show', txt );
}

var dialog = new Dialog();

//添加监听事件show
dialog.on( 'show', function(txt){ console.log( txt )});

//执行method show时,就会触发其内定义的show events,输出 this is show
dialog.show( 'this is show' );

Salin selepas log masuk
6. Ringkasan

Nodejs menyediakan mekanisme pemantauan yang baik dan juga digunakan dalam semua modulnya Ia menyokong mod I/O yang paling tersendiri Contohnya, apabila kami memulakan perkhidmatan http, ia akan memantau sambungan / tutupnya, dan bila http.request Pantau data/tamat, dsb. Memahami mekanisme pemantauan adalah asas untuk mempelajari dan memahami nodej, dan juga bermanfaat untuk menambah baik idea pengaturcaraan.

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan