>웹 프론트엔드 >JS 튜토리얼 >Nodejs 관찰자 패턴 소개

Nodejs 관찰자 패턴 소개

不言
不言원래의
2018-06-30 16:11:121380검색

이 글은 주로 Nodejs 관찰자 모드 관련 정보를 소개합니다. 필요하신 분들은 참고하시면 됩니다.

1. 소개

Nodejs는 최근에 API를 검토하고 더 많은 새로운 기능을 사용해 보겠습니다. . 더 높은 수준의 숙달을 위해 이 API 요약은 영어 버전의 간단한 중국어 버전과 다릅니다. 모든 사람에게 도움이 되길 바랍니다. 핵심 Events

Nodejs 이벤트는 Nodejs의 핵심 메커니즘을 지원하는 관찰자 패턴을 구현하며, http/fs/mongoose 등은 모두 이벤트를 상속하고 청취 이벤트를 추가할 수 있습니다. 이 디자인 패턴은 클라이언트 측 구성 요소 프로그래밍 아이디어에 자주 사용됩니다. 먼저 이 패턴을 간략하게 이해하겠습니다.

내가 처음으로 관찰자 패턴을 접한 것은 Extjs 프레임워크의 Ext.util.observable 소스 코드에서였습니다. 그 당시 저는 js를 처음 접했고 이 패턴이 매우 강력하다고 느꼈습니다. 제가 접하게 된 디자인 패턴은 나중에 underscore.js 소스 코드에서도 보았습니다. 예, 저는 컴포넌트를 작성할 때 기본적으로 이 아이디어를 따릅니다.

관찰자 모드는 on('show', callback)과 같은 모니터링 이벤트를 객체에 추가하는 것인데, 이는 show와 같은 조건을 충족할 때 객체에 의해 트리거됩니다. 돔.

입력에 대한 키업 모니터링을 추가하면 해당 값을 출력하는 것이 목적입니다

$( 'input' ).on( 'keyup', function(){
   console.log( this.value );
} );

이렇게 콘텐츠를 입력하면 해당 값이 로그에 출력됩니다.

하지만 Dialog와 같은 구성 요소를 만들 때 가장 일반적으로 사용되는 표시/숨기기 이벤트를 어떻게 모니터링합니까?

기본 방법은

var dialog = new Dialog({
  content: '这里是弹出框的内容',
  show: function(){
    console.log( '当弹框时输出此段内容' );
  }
});

과 같이 인스턴스화 중에 콜백을 직접 구성하는 것입니다. 2. 관찰자 모드 구현

먼저 기본 모니터링을 제공하는 이벤트 개체를 구현합니다. 이벤트는 json 형식입니다. 객체의 _events

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

에 있는 스택에 푸시합니다. 그런 다음 객체의 속성을 복사하는 함수를 추상화합니다.

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

대화 상자를 구현합니다.

만들기; 방법: 표시/숨기기;

효과를 볼 때 이 스타일을 추가하세요

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

컴포넌트 구현

var Dialog = function( config ){
  this.config = config;
  this.init( this.config );
};

확장 속성

extend( Dialog.prototype, {

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

  render: function( config ){
    this.el = $( &#39;<p>&#39; ).addClass( &#39;dialog&#39; );
    this.el.html( config.content );
    $( &#39;body&#39; ).append( this.el );
  },

  show: function( param ){
    this.el.fadeIn();
    this.emit( &#39;show&#39;, param );
  },

  hide: function( param ){
    this.el.fadeOut();
    this.emit( &#39;hide&#39;, param );
  }

}, Events );

인스턴스를 생성하고 3개의 표시 및 숨기기 청취 이벤트를 추가하세요

var dialog = window.dialog = new Dialog({
  content: &#39;dialog one&#39;
});

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

//do something

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

//do something

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

//do something

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

//do something

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

//do something

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

6개의 다른 표시 이벤트와 숨기기 이벤트를 6번 추가했습니다.

Dialog.show()가 실행되면 해당 로그 3개가 출력됩니다. 추가된 이벤트는 그림과 같이 Dialog._events에 저장됩니다.


추가된 세 개의 쇼는 모두 성공적으로 출력되며 이벤트는 _events 속성에 저장됩니다Nodejs 관찰자 패턴 소개

nodejs Events도 이 프로세스를 구현합니다.

3. 구조

var Events = require( &#39;events&#39; );
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( &#39;show&#39;, function( txt ){ console.log( &#39;one &#39; + txt )})
myEmitter.on( &#39;show&#39;, function( txt ){ console.log( &#39;tow &#39; + txt )})
myEmitter.on( &#39;hide&#39;, function( txt ){ console.log( &#39;one &#39; + txt )})
myEmitter.emit( &#39;show&#39;, &#39;show&#39; );
myEmitter.setMaxListeners( 10 );
console.log( myEmitter );
/*
{ domain: null,
  _events: { show: [ [Function], [Function] ], hide: [Function] }, //添加后的事情,以json形式存放
  _maxListeners: 10 }
*/

4. API

제공되는 메서드는 on이며, 이는 모두 addListener의 약어입니다. 다른 속성은 모두 인스턴스에 추가됩니다.

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( &#39;show&#39;, &#39;prompt content&#39; );
 参数1为事件名,参数二供on回调里的参数
 */

addListener: [Function: addListener],
 /*
添加监听事件
emitter.addListener( event, listener );
如 myEmitter.addListener( &#39;show&#39;, 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( &#39;show&#39;, function( txt ){ console.log( txt ) } );
当myEmitter.emit执行第二次时没有输出
 */

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

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

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

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

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

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

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

5. Application

이벤트를 사용하면 일반적으로 위의 API 섹션에 표시된 대로 직접 인스턴스화합니다.

그러나 이벤트에 구성 요소도 구현하는 경우 이전 Dialog와 같은 nodejs 측에서 Dialog에도 Events 기능을 갖게 하려면 어떻게 해야 할까요? Extjs

에 의해 구현된 확장 솔루션을 사용하여 대화 상자 빌더

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 == &#39;object&#39;){
      overrides = sp;
      sp = sb;
      sb = overrides.constructor != oc ? 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( &#39;show&#39;, txt );
}

var dialog = new Dialog();

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

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

를 만들 수 있습니다. 이러한 방식으로 메서드가 호출되면 이벤트가 트리거됩니다

. 6. 요약

nodejs는 매우 우수한 모니터링 메커니즘을 갖추고 있으며 nodejs의 가장 독특한 I/O 모드를 지원합니다. 연결/닫기, http.request 시 데이터/종료 등을 모니터링합니다. 모니터링 메커니즘을 이해하는 것은 nodejs의 기초를 배우고 이해하는 데 유익하며, 프로그래밍 사고를 향상시키는 데에도 도움이 됩니다.

위 내용은 이 글의 전체 내용입니다. 모든 분들의 학습에 도움이 되었으면 좋겠습니다. 더 많은 관련 내용은 PHP 중국어 홈페이지를 주목해주세요!

관련 권장 사항:

Node.js에서 Buffer를 사용하여 바이너리 데이터를 인코딩 및 디코딩하는 방법


NodeJs의 기본 구문 및 유형 소개


위 내용은 Nodejs 관찰자 패턴 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.