노드에서 많은 객체가 이벤트를 방출합니다. 예를 들어, TCP 서버는 클라이언트가 연결을 요청할 때마다 "Connect"이벤트를 전송하며, 예를 들어 전체 데이터 조각을 읽을 때마다 파일 시스템이 "데이터"이벤트를 전송합니다. 이 객체를 노드에서 이벤트 이미 터라고합니다. 이벤트 송신기를 사용하면 프로그래머가 관심있는 이벤트를 구독하고 콜백 함수를 관련 이벤트에 바인딩하여 이벤트 송신기가 이벤트를 방출 할 때마다 콜백 함수가 호출되도록합니다. 게시/구독 모드는 기존 GUI 모드와 매우 유사합니다. 예를 들어 버튼을 클릭하면 프로그램이 해당 알림을받습니다. 이 모델을 사용하면 서버 프로그램이 클라이언트 연결, 소켓에서 사용 가능한 데이터 또는 파일 폐쇄와 같은 일부 이벤트가 발생하면 반응 할 수 있습니다.
자신만의 이벤트 송신기를 만들 수도 있습니다. 실제로 Node는 자신의 이벤트 송신기를 만들기 위해 기본 클래스로 사용할 수있는 특수 Eventemitter 의사 클래스를 제공합니다.
콜백 모드를 이해합니다
비동기 프로그래밍은 기능 통화의 끝을 나타내는 기능 리턴 값을 사용하지 않지만 후속 패스 스타일을 채택합니다.
"Contatuation-Passing Style"(CPS : Continuation-Passing Style)은 프로그래밍 스타일이며 프로세스 제어가 다음 작업으로 명시 적으로 전달됩니다 ...
CPS 스타일 함수는 기능을 추가 매개 변수로 받아들입니다. 이 기능은 다음 프로그램 제어 프로세스를 명시 적으로 지적하는 데 사용됩니다. CPS 함수가 "반환 값"을 계산하면 프로그램의 다음 프로세스를 나타내는 함수를 호출하고 CPS 함수의 "반환 값"을 매개 변수로 취합니다.
wikipedia -http://en.wikipedia.org/wiki/continuation-passing_style에서
이 프로그래밍 스타일에서 각 함수는 실행 후 콜백 함수를 호출하여 프로그램이 계속 실행될 수 있도록합니다. 나중에 JavaScript 가이 프로그래밍 스타일에 매우 적합하다는 것을 이해할 것입니다. 다음은 노드 아래 메모리에 파일을로드하는 예입니다.
코드 사본은 다음과 같습니다.
var fs = 요구 ( 'fs');
fs.readfile ( '/etc/passwd', function (err, filecontent) {
if (err) {
오류를 던지십시오.
}
console.log ( '파일 내용', filecontent.toString ());
});
이 예에서는 Fs.ReadFile의 두 번째 매개 변수로 인라인 익명 기능을 전달합니다. 실제로 이것은 프로그램 실행의 후속 프로세스를 콜백 함수에 전달하기 때문에 CPS 프로그래밍을 사용합니다.
보시다시피, 콜백 함수의 첫 번째 매개 변수는 오류 객체입니다. 프로그램에서 오류가 발생하면이 매개 변수는 오류 클래스의 인스턴스가됩니다. 이것은 노드에서 CPS 프로그래밍을위한 일반적인 패턴입니다.
이벤트 송신기 모드를 이해합니다
표준 콜백 모드에서, 함수는 실행될 함수의 매개 변수로 전달된다. 이 모드는 함수가 완료된 후 클라이언트에 알리는 시나리오에서 매우 잘 작동합니다. 그러나 함수 실행 중에 여러 이벤트가 발생하거나 이벤트가 여러 번 발생하면이 패턴이 적합하지 않습니다. 예를 들어, 소켓이 사용 가능한 데이터를 수신 할 때마다 알림을 받으려면 표준 콜백 모드 가이 시나리오에서 그다지 유용하지 않음을 알 수 있습니다. 현재 이벤트 송신기 모드는 편리합니다. 표준 인터페이스 세트를 사용하여 이벤트 생성기 및 이벤트 리스너를 명확하게 분리 할 수 있습니다.
이벤트 생성기 모드를 사용할 때는 송신기와 하나 이상의 이벤트 리스너 등 둘 이상의 객체가 관련됩니다.
이름에서 알 수 있듯이 이벤트 송신기는 이벤트를 생성 할 수있는 객체입니다. 이벤트 리스너는 다음 예제와 같이 특정 유형의 이벤트를 듣기 위해 이벤트 송신기에 바인딩 된 코드입니다.
코드 사본은 다음과 같습니다.
var req = http.request (옵션, 함수 (응답) {
response.on ( "data", function (data) {
Console.log ( "응답의 일부 데이터", 데이터);
});
response.on ( "end", function () {
Console.log ( "응답 종료");
});
});
req.end ();
이 코드는 Node의 http.request API를 사용하여 원격 HTTP 서버에 액세스하기위한 HTTP 요청을 작성할 때 필요한 두 단계를 보여줍니다 (이후 장 참조). 첫 번째 줄은 "연속 패스 스타일"(CPS : Continuation-Passing Style)을 채택하여 HTTP가 응답 할 때 호출 될 인라인 함수를 전달합니다. HTTP 요청 API는 HTTP.Request 함수가 실행 된 후에 프로그램이 후속 작업을 계속 수행해야하기 때문에 여기서는 CPS를 사용합니다.
http.request가 실행되면 익명 콜백 함수가 호출되고 HTTP 응답 객체가 매개 변수로 전달됩니다. 이 HTTP 응답 객체는 이벤트 송신기입니다. 노드 문서에 따르면 데이터 및 종료를 포함한 많은 이벤트를 방출 할 수 있습니다. 등록 된 콜백 기능은 이벤트가 발생할 때마다 호출됩니다.
수업으로 요청 된 작업이 완료된 후에 실행 권한을 되 찾아야 할 때 CPS 모드를 사용하고 이벤트가 여러 번 발생할 수있는 경우 이벤트 송신기 모드를 사용하십시오.
이벤트 유형을 이해합니다
전송 된 이벤트에는 문자열로 표시되는 유형이 있습니다. 이전 예제에는 두 가지 이벤트 유형이 포함되어 있습니다 : "데이터"와 "END"는 이벤트 송신기로 정의 된 문자열입니다. 그러나 이벤트 유형은 일반적으로 빈 문자가 포함되지 않은 소문자 단어로 구성된다는 것이 일반적으로 구성됩니다.
이벤트 송신기 API에는 내성 메커니즘이 없기 때문에 이벤트 송신기가 생성 할 수있는 이벤트 유형을 유추하기 위해 코드를 사용할 수 없으므로 사용중인 API에는 이러한 유형의 이벤트를 방출 할 수 있음을 나타내는 문서가 있어야합니다.
이벤트가 발생하면 이벤트 송신기는 이벤트와 관련된 리스너를 호출하고 관련 데이터를 리스너에게 매개 변수로 전달합니다. 이전 예제 http.request에서 "data"이벤트 콜백 함수는 데이터 객체를 첫 번째 및 유일한 매개 변수로 받아들이고 "END"는 데이터를 허용하지 않습니다. API 계약의 일부로서 이러한 매개 변수는 API의 저자에 의해 주관적으로 정의됩니다. 이러한 콜백 함수의 매개 변수 서명은 각 이벤트 이미 터의 API 문서에 설명됩니다.
이벤트 송신기는 모든 유형의 이벤트를 제공하는 인터페이스이지만 "오류"이벤트는 노드에서 특별한 구현입니다. 노드의 대부분의 이벤트 송신기는 프로그램에서 오류가 발생할 때 "오류"이벤트를 생성합니다. 프로그램이 이벤트 송신기의 "오류"이벤트를 듣지 않으면 이벤트 송신기는 오류가 발생할 때 끊임없는 예외를 위로 표시하고 던지게됩니다.
Node Perl에서 다음 코드를 실행하여 효과를 테스트 할 수있어 두 가지 이벤트를 생성 할 수있는 이벤트 송신기를 시뮬레이션합니다.
코드 사본은 다음과 같습니다.
var em = new (require ( 'event'). Eventemitter) ();
em.emit ( 'event1');
em.emit ( '오류', 새로운 오류 ( '내 실수'));
다음 출력이 표시됩니다.
코드 사본은 다음과 같습니다.
var em = new (require ( 'event'). Eventemitter) ();
한정되지 않은
> em.emit ( 'event1');
거짓
> em.emit ( '오류', 새로운 오류 ( '내 실수'));
오류 : 내 실수
대체 : 1 : 18
atredserver.eval (repl.js : 80 : 21)
repl.js : 190 : 20
atredserver.eval (repl.js : 87 : 5)
인터페이스.
at interface.emit (events.js : 67 : 17)
at interface._online (readline.js : 162 : 10)
at interface._line (readline.js : 426 : 8)
at interface._ttywrite (readline.js : 603 : 14)
at ReadStream.
>
코드의 2 행에서 "event1"이라는 이벤트는 효과없이 방출되지만 "오류"이벤트가 방출되면 오류가 스택에 던져집니다. Perl Command Line 환경에서 프로그램이 실행되지 않는 경우, 잡힌 예외로 인해 프로그램이 충돌합니다.
이벤트 송신기 API 사용
이벤트 송신기 모드 (예 : TCP 소켓, HTTP 요청 등)를 구현하는 객체는 다음과 같은 방법 세트를 구현합니다.
코드 사본은 다음과 같습니다.
.adlistener 및 .on- 지정된 유형의 이벤트에 대한 이벤트 리스너 추가
.Once- 지정된 유형의 이벤트에 대해 한 번만 실행하는 이벤트 리스너를 바인딩합니다.
.removeEventListener- 지정된 이벤트에 바인딩 된 리스너 삭제
.removealleventListener- 지정된 이벤트에 바인딩 된 모든 청취자 삭제
아래에 자세히 소개하겠습니다.
.addlistener () 또는 .on ()을 사용하여 바인딩 콜백 함수
이벤트 유형 및 콜백 함수를 지정하면 이벤트가 발생할 때 수행 된 작업을 등록 할 수 있습니다. 예를 들어 파일이 데이터 스트림을 읽을 때 사용 가능한 데이터 블록이 있으면 "데이터"이벤트가 발생합니다. 다음 코드는 콜백 함수를 전달하여 프로그램에 데이터 이벤트가 발생했음을 알리도록하는 방법을 보여줍니다.
코드 사본은 다음과 같습니다.
함수 수신자 (데이터) {
Console.log ( "파일 읽기 스트림에서 얻은 데이터 : %j", 데이터);
}
readstream.addlistener ( "data", receptionata);
.on을 사용할 수도 있습니다. 다음 코드는 위와 동일합니다.
코드 사본은 다음과 같습니다.
함수 수신자 (데이터) {
Console.log ( "파일 읽기 스트림에서 얻은 데이터 : %j", 데이터);
}
readstream.on ( "data", receptionata);
이전 코드에서는 콜백 함수로 사전에 정의 된 이름의 기능을 사용할 수 있으며 인라인 익명 함수를 사용하여 코드를 단순화 할 수도 있습니다.
코드 사본은 다음과 같습니다.
readstream.on ( "data", function (data) {
Console.log ( "파일 읽기 스트림에서 얻은 데이터 : %j", 데이터);
});
앞에서 언급했듯이 콜백 함수로 전달 된 매개 변수 및 서명 수는 특정 이벤트 송신기 개체 및 이벤트 유형에 따라 다릅니다. 그들은 표준화되지 않습니다. "데이터"이벤트는 데이터 버퍼 객체를 전달할 수 있고, "오류"이벤트는 오류 객체를 전달하며, 데이터 흐름의 "종료"이벤트는 데이터를 이벤트 리스너에게 전달하지 않습니다.
여러 이벤트 리스너를 묶습니다
이벤트 송신기 모드는 여러 이벤트 리스너가 동일한 이벤트 송신기의 동일한 이벤트 유형을 다음과 같이 경청 할 수 있습니다.
코드 사본은 다음과 같습니다.
여기에 몇 가지 데이터가 있습니다.
여기에도 몇 가지 데이터가 있습니다.
이벤트 송신기는 리스너가 등록 된 순서로 지정된 이벤트 유형에 바인딩 된 모든 리스너를 호출 할 책임이 있습니다.
1. 이벤트가 발생하면 이벤트 청취자가 즉시 호출되지 않을 수 있으며, 그 전에 다른 이벤트 리스너가 호출 될 수 있습니다.
2. 스택에 던져지는 것은 비정상적이며 코드의 버그 때문일 수 있습니다. 이벤트가 전송되면 이벤트 청취자가 호출 될 때 예외를 던지면 일부 이벤트 청취자가 호출되지 않을 수 있습니다. 이 경우 이벤트 송신기는 예외를 포착하여 처리 할 수도 있습니다.
다음 예를 참조하십시오.
코드 사본은 다음과 같습니다.
readstream.on ( "data", function (data) {
새로운 오류를 던지십시오 ( "잘못된 일이 일어났습니다");
});
readstream.on ( "data", function (data) {
Console.log ( '여기에도 몇 가지 데이터가 있습니다.');
});
첫 번째 청취자는 예외를 던지기 때문에 두 번째 청취자는 호출되지 않습니다.
.removelistener ()를 사용하여 이벤트 송신기에서 이벤트 리스너를 제거하십시오.
더 이상 객체의 이벤트에 관심이없는 경우 이벤트 유형 및 콜백 함수를 지정하여 등록 된 이벤트 리스너를 취소 할 수 있습니다.
코드 사본은 다음과 같습니다.
함수 수신자 (데이터) {
Console.log ( "파일 읽기 스트림에서 얻은 데이터 : %j", 데이터);
}
readstream.on ( "data", receptionata);
// ...
readstream.removelistener ( "data", reciverata);
이 예에서 마지막 줄은 이벤트 송신기 개체에서 향후 언제든지 호출 될 수있는 이벤트 리스너를 제거합니다.
리스너를 삭제하려면 콜백 함수의 이름을 추가하고 삭제할 때 콜백 함수의 이름이 필요하므로 콜백 함수의 이름을 지정해야합니다.
.once ()를 사용하여 콜백 함수를 최대 한 번에 실행할 수 있습니다.
최대 한 번에 실행되는 이벤트를 듣고 싶거나 이벤트가 처음 발생하는 경우에만 관심이 있으시면 .once () 함수를 사용할 수 있습니다.
코드 사본은 다음과 같습니다.
함수 수신자 (데이터) {
Console.log ( "파일 읽기 스트림에서 얻은 데이터 : %j", 데이터);
}
readstream.once ( "data", receptionata);
위 코드에서 수신자 기능은 한 번만 호출됩니다. readStream 객체가 데이터 이벤트를 제출하면 수신자 콜백 함수가 한 번만 트리거됩니다.
실제로는 편리한 방법입니다.
코드 사본은 다음과 같습니다.
var eventimitter = 요구 ( "이벤트"). 이벤트 미터;
eventimitter.prototype.once = function (유형, 콜백) {
var that = this;
this.on (type, function learser () {
that.removelistener (유형, 리스너);
Callback.Apply (That, Arguments);
});
};
위의 코드에서는 Eventemitter.prototype.once 함수를 재정의하고 Eventemitter에서 상속 된 각 객체의 한 번 함수를 재정의합니다. 코드는 단순히 .on () 메소드를 사용합니다. 이벤트가 접수되면 .removeeventListener ()를 사용하여 콜백 함수의 등록을 취소하고 원래 콜백 함수를 호출하십시오.
참고 : 이전 코드는 객체를 받아들이고 포함 된이 변수와 매개 변수 배열로 가져 오는 function.apply () 메소드를 사용합니다. 이전 예제에서, 수정되지 않은 매개 변수 배열은 이벤트 송신기를 통해 콜백 함수로 투명하게 전달됩니다.
.removealllisteners ()로 이벤트 송신기에서 모든 이벤트 리스너를 제거하십시오.
다음과 같이 이벤트 송신기에서 지정된 이벤트 유형에 등록 된 모든 리스너를 제거 할 수 있습니다.
코드 사본은 다음과 같습니다.
Emitter.removealllisteners (유형);
예를 들어, 다음과 같은 모든 프로세스 인터럽트 신호의 리스너를 취소 할 수 있습니다.
코드 사본은 다음과 같습니다.
process.removealllisteners ( "sigterm");
참고 : 레슨으로 삭제 된 내용을 정확히 알 때만이 기능 만 사용하는 것이 좋습니다. 그렇지 않으면 응용 프로그램의 다른 부분에서 이벤트 리스너 컬렉션을 삭제하거나 프로그램의 해당 부분이 청취자 직접 제거 할 수 있도록해야합니다. 그러나 무엇이든,이 기능은 이벤트 송신기를 닫을 준비를하거나 순서대로 전체 프로세스를 종료 할 때와 같은 드문 시나리오에서 여전히 유용합니다.
이벤트 송신기를 만듭니다
이벤트 송신기는 프로그래밍 인터페이스를 더 일반적인 방식으로 더 일반화합니다. 일반적이고 이해하기 쉬운 프로그래밍 모드에서 클라이언트는 다양한 기능을 직접 호출하는 반면 이벤트 송신기 모드에서는 클라이언트가 다양한 이벤트에 제대로 연결되어 프로그램을보다 유연하게 만듭니다. (번역기 주 :이 문장은 자신감이 없습니다. 원본 텍스트를 게시합니다. 이벤트 이미 터는 프로그래밍 인터페이스를보다 일반적으로 만드는 좋은 방법을 제공합니다. 일반적인 이해 패턴을 사용하면 클라이언트는 기능을 호출하는 대신 이벤트에 바인딩하여 프로그램을보다 유연하게 만듭니다).
또한 이벤트 송신기를 사용하면 동일한 이벤트에서 다수의 관련없는 청취자를 바인딩하는 것과 같은 많은 기능을 얻을 수 있습니다.
노드 이벤트 송신기에서 상속됩니다
Node의 이벤트 이미 터 모드에 관심이 있고 자신의 응용 프로그램에서 사용하려는 경우 Eventemitter를 상속하여 의사 클래스를 만들 수 있습니다.
코드 사본은 다음과 같습니다.
util = 요구 ( 'util');
var eventimitter = require ( 'events'). Eventemitter;
// 이것은 myclass의 생성자입니다.
var myclass = function () {
}
util.inherits (myclass, eventemitter);
참고 : util.inherits MyClass의 프로토 타입 체인을 생성하여 MyClass 인스턴스가 Eventemitter의 프로토 타입 메소드를 사용할 수 있도록합니다.
런칭 이벤트
MyClass는 EventeMitter에서 상속을 통해 다음과 같은 이벤트를 시작할 수 있습니다.
코드 사본은 다음과 같습니다.
myclass.prototype.somemethod = function () {
this.emit ( "사용자 정의 이벤트", "인수 1", "인수 2");
};
위의 코드에서는 MyClass 인스턴스에서 Somemethond 메소드를 호출 할 때 "Cuteom Event"라는 이벤트가 방출됩니다. 이 이벤트는 또한 두 개의 문자열을 데이터로 방출합니다 : "argument 1"및 "argument 2"는 이벤트 리스너의 매개 변수로 전달됩니다.
MyClass 인스턴스의 클라이언트는 다음과 같은 "사용자 정의 이벤트"이벤트를들을 수 있습니다.
코드 사본은 다음과 같습니다.
var myinstance = new myclass ();
myinstance.on ( '사용자 정의 이벤트', 함수 (str1, str2) {
console.log ( 'str1 %s 및 str2 %s!', str1, str2로 사용자 정의 이벤트가 있습니다);
});
예를 들어, "틱"이벤트를 한 번에 한 번 방출하는 시세 클래스를 만들 수 있습니다.
코드 사본은 다음과 같습니다.
var util = 요구 ( 'util'),
eventItter = require ( 'events'). EventEmitter;
var ticker = function () {
var self = 이것;
setInterval (function () {
self.emit ( 'tick');
}, 1000);
};
util.inherits (Ticker, Eventemitter);
Ticker 클래스를 사용하는 고객은 Ticker 클래스를 사용하고 "진드기"이벤트를 듣는 방법을 보여줄 수 있습니다.
코드 사본은 다음과 같습니다.
var ticker = new Ticker ();
Ticker.on ( "진드기", function () {
Console.log ( "진드기");
});
요약
이벤트 송신기 모드는 특정 이벤트의 코드 세트에서 이벤트 송신기 개체를 분리하는 데 사용할 수있는 재창조 패턴입니다.
event_emitter.on ()을 사용하여 특정 유형의 이벤트에 대한 리스너를 등록하고 event_emitter.removelistener ()로 등록 해제 할 수 있습니다.
이벤트 미터를 상속하고 간단히 .emit () 함수를 사용하여 고유 한 이벤트 이미 터를 만들 수도 있습니다.