Rumah  >  Artikel  >  hujung hadapan web  >  Penjelasan terperinci tentang pengikatan peristiwa menggunakan corak pemancar peristiwa dalam Node.js_node.js

Penjelasan terperinci tentang pengikatan peristiwa menggunakan corak pemancar peristiwa dalam Node.js_node.js

WBOY
WBOYasal
2016-05-16 16:39:321398semak imbas

Dalam Node, banyak objek memancarkan peristiwa. Sebagai contoh, pelayan TCP akan memancarkan peristiwa "sambung" setiap kali pelanggan meminta sambungan Contohnya, setiap kali keseluruhan blok data dibaca, sistem fail akan memancarkan peristiwa "data". Objek ini dipanggil pemancar peristiwa dalam Node. Pemancar acara membenarkan pengaturcara untuk melanggan acara yang mereka minati dan mengikat fungsi panggil balik pada acara yang berkaitan, supaya fungsi panggil balik dipanggil setiap kali pemancar acara memancarkan acara. Model terbitkan/langgan sangat serupa dengan model GUI tradisional Contohnya, apabila butang diklik, program akan menerima pemberitahuan yang sepadan. Menggunakan mod ini, program pelayan boleh bertindak balas apabila beberapa peristiwa berlaku, seperti apabila pelanggan menyambung, data tersedia pada soket atau apabila fail ditutup.

Anda juga boleh mencipta pemancar acara anda sendiri Malah, Node menyediakan kelas pseudo EventEmitter, yang boleh digunakan sebagai kelas asas untuk mencipta pemancar acara anda sendiri.

Memahami corak panggil balik

Pengaturcaraan tak segerak tidak menggunakan nilai pulangan fungsi untuk menunjukkan penamatan panggilan fungsi, tetapi menggunakan gaya penghantaran pengganti.

"Gaya hantaran berterusan" (CPS: Gaya hantaran berterusan) ialah gaya pengaturcaraan di mana kawalan proses dihantar secara eksplisit ke operasi seterusnya...

Fungsi gaya CPS akan menerima fungsi sebagai parameter tambahan Fungsi ini digunakan untuk menunjukkan secara jelas proses seterusnya yang dikawal oleh program Apabila fungsi CPS mengira "nilai pulangannya", ia akan memanggil fungsi yang mewakili langkah seterusnya bagi fungsi proses dan mengambil "nilai pulangan" fungsi CPS sebagai parameternya.

Dari Wikipedia - http://en.wikipedia.org/wiki/Continuation-passing_style

Dalam gaya pengaturcaraan ini, setiap fungsi akan memanggil fungsi panggil balik selepas pelaksanaan, supaya atur cara boleh terus berjalan. Anda akan faham kemudian bahawa JavaScript sangat sesuai untuk gaya pengaturcaraan ini Berikut ialah contoh memuatkan fail ke dalam memori di bawah Node:

Salin kod Kod adalah seperti berikut:

var fs = memerlukan('fs');

fs.readFile('/etc/passwd', function(err, fileContent) {

jika (err) {

buang err;

}

console.log('kandungan fail', fileContent.toString());

});

Dalam contoh ini, anda menghantar fungsi tanpa nama sebaris sebagai parameter kedua fs.readFile Sebenarnya, ini adalah pengaturcaraan menggunakan CPS, kerana anda menyerahkan proses pelaksanaan program yang seterusnya kepada fungsi panggil balik.

Seperti yang anda lihat, parameter pertama fungsi panggil balik ialah objek ralat Jika ralat berlaku dalam program, parameter ini akan menjadi contoh kelas Ralat Ini adalah corak biasa dalam pengaturcaraan CPS dalam Node.

Memahami Corak Pemancar Acara

Dalam mod panggil balik standard, fungsi dihantar sebagai parameter kepada fungsi yang akan dilaksanakan. Mod ini berfungsi dengan baik dalam senario di mana pelanggan perlu dimaklumkan selepas fungsi selesai. Walau bagaimanapun, model ini tidak sesuai jika berbilang peristiwa berlaku semasa pelaksanaan fungsi atau jika peristiwa itu berlaku berulang kali beberapa kali. Sebagai contoh, anda ingin dimaklumkan setiap kali soket menerima data yang tersedia Dalam senario ini, anda akan mendapati bahawa mod panggil balik standard tidak begitu mudah untuk digunakan satu set antara muka standard untuk Pemisahan jelas penjana acara dan pendengar acara.

Apabila menggunakan corak penjana peristiwa, dua atau lebih objek terlibat - pemancar peristiwa dan satu atau lebih pendengar peristiwa.

Pemancar peristiwa, seperti namanya, ialah objek yang boleh menjana peristiwa. Pendengar acara ialah kod yang terikat kepada pemancar acara untuk mendengar jenis acara tertentu, seperti contoh berikut:

Salin kod Kod adalah seperti berikut:

var req = http.request(options, function(respons) {

response.on("data", function(data) {

console.log("beberapa data daripada respons", data);

});

response.on("end", function() {

console.log("response ended");

});

});

req.end();

Kod ini menunjukkan dua langkah yang diperlukan untuk membuat permintaan HTTP untuk mengakses pelayan HTTP jauh menggunakan API http.request Node (lihat bab kemudian). Baris pertama menggunakan "gaya terusan-laluan" (CPS: Gaya laluan-sambungan), menghantar fungsi sebaris yang akan dipanggil apabila respons HTTP dibuat. API permintaan HTTP menggunakan CPS di sini kerana program perlu meneruskan operasi seterusnya selepas fungsi http.request dilaksanakan.

Apabila http.request dilaksanakan, fungsi panggil balik tanpa nama akan dipanggil, dan kemudian objek respons HTTP akan dihantar kepadanya sebagai parameter Objek respons HTTP ini adalah pemancar peristiwa memancarkan data, tamat pada Untuk banyak acara, fungsi panggil balik yang anda daftarkan akan dipanggil setiap kali peristiwa itu berlaku.

Sebagai peraturan biasa, gunakan corak CPS apabila anda perlu mendapatkan semula hak pelaksanaan selepas operasi yang diminta selesai dan gunakan corak Pemancar Peristiwa apabila peristiwa boleh berlaku beberapa kali.

Memahami jenis acara

Peristiwa yang dipancarkan mempunyai jenis yang diwakili oleh rentetan Contoh sebelumnya termasuk dua jenis peristiwa: "data" dan "akhir". perkataan yang tidak mengandungi aksara nol.

Anda tidak boleh menggunakan kod untuk membuat kesimpulan jenis peristiwa yang boleh dihasilkan oleh pemancar peristiwa, kerana API pemancar peristiwa tidak mempunyai mekanisme introspeksi, jadi API yang anda gunakan harus mempunyai dokumentasi untuk menunjukkan jenis peristiwa yang boleh dipancarkannya.

Sebaik sahaja peristiwa berlaku, pemancar peristiwa akan memanggil pendengar yang berkaitan dengan peristiwa dan menghantar data yang berkaitan kepada pendengar sebagai parameter. Dalam contoh http.request sebelumnya, fungsi panggil balik peristiwa "data" menerima objek data sebagai parameter pertama dan satu-satunya, manakala "akhir" tidak menerima sebarang data Parameter ini juga ditentukan oleh pengarang API sebagai sebahagian daripada API kontrak. Ditakrifkan secara subjektif, tandatangan parameter bagi fungsi panggil balik ini juga diterangkan dalam dokumentasi API setiap pemancar peristiwa.

Walaupun pemancar peristiwa ialah antara muka yang menyediakan semua jenis acara, peristiwa "ralat" ialah pelaksanaan khas dalam Node. Kebanyakan pemancar peristiwa dalam Node akan menjana peristiwa "ralat" apabila ralat berlaku dalam atur cara Jika atur cara tidak mendengar peristiwa "ralat" pemancar peristiwa, pemancar peristiwa akan melihat dan membuangnya apabila ralat berlaku. Pengecualian yang tidak tertangkap.

Anda boleh menjalankan kod berikut dalam Node PERL untuk menguji kesan Ia mensimulasikan pemancar peristiwa yang boleh menjana dua peristiwa:

Salin kod Kod adalah seperti berikut:

var em = baru (memerlukan('events').EventEmitter)();

em.emit('event1');

em.emit('error', new Error('My mistake'));

Anda akan melihat output berikut:

Salin kod Kod adalah seperti berikut:

var em = baru (memerlukan('events').EventEmitter)();

tidak ditentukan

> em.emit('event1');

palsu

> em.emit('error', new Error('My mistake'));

Ralat: Kesilapan saya

pada balasan:1:18

di REPLServer.eval (repl.js:80:21)

di repl.js:190:20

di REPLServer.eval (repl.js:87:5)

di Antara Muka. (repl.js:182:12)

di Interface.emit (events.js:67:17)

di Antara Muka._onLine (readline.js:162:10)

di Interface._line (readline.js:426:8)

di Antara Muka._ttyWrite (readline.js:603:14)

di ReadStream. (readline.js:82:12)

>

Dalam baris 2 kod, peristiwa yang dipanggil "event1" dipancarkan secara rawak, yang tidak mempunyai kesan Walau bagaimanapun, apabila acara "ralat" dipancarkan, ralat dibuang ke tindanan. Jika program tidak berjalan dalam persekitaran baris arahan PERL, program akan ranap disebabkan oleh pengecualian yang tidak ditangkap.

Menggunakan API Pemancar Acara

Sebarang objek yang melaksanakan corak pemancar peristiwa (seperti Soket TCP, permintaan HTTP, dll.) melaksanakan set kaedah berikut:

Salin kod Kod adalah seperti berikut:

.addListener dan .on - tambahkan pendengar acara untuk jenis acara tertentu
.sekali - Ikat pendengar acara yang melaksanakan sekali sahaja untuk jenis acara yang ditentukan
.removeEventListener - Alih keluar pendengar yang terikat pada acara yang ditentukan
.removeAllEventListener - Alih keluar semua pendengar yang terikat pada acara yang ditentukan

Kami memperkenalkannya secara terperinci di bawah.

Gunakan .addListener() atau .on() untuk mengikat fungsi panggil balik

Dengan menyatakan jenis acara dan fungsi panggil balik, anda boleh mendaftarkan operasi untuk dilakukan apabila acara itu berlaku. Sebagai contoh, jika terdapat blok data yang tersedia apabila fail membaca strim data, peristiwa "data" akan dipancarkan Kod berikut menunjukkan cara membenarkan program memberitahu anda bahawa peristiwa data telah berlaku dengan menghantar dalam fungsi panggil balik .

Salin kod Kod adalah seperti berikut:

fungsi receiveData(data) {

console.log("mendapat data daripada strim baca fail: %j", data);

}

readStream.addListener(“data”, receiveData);

Anda juga boleh menggunakan .on, iaitu singkatan untuk .addListener Kod berikut adalah sama seperti di atas:

Salin kod Kod adalah seperti berikut:

fungsi receiveData(data) {

console.log("mendapat data daripada strim baca fail: %j", data);

}
readStream.on(“data”, receiveData);

Kod sebelumnya menggunakan fungsi bernama pratakrif sebagai fungsi panggil balik Anda juga boleh menggunakan fungsi tanpa nama sebaris untuk memudahkan kod:

Salin kod Kod adalah seperti berikut:

readStream.on("data", fungsi(data) {

console.log("mendapat data daripada strim baca fail: %j", data);

});


Seperti yang dinyatakan sebelum ini, bilangan dan tandatangan parameter yang dihantar ke fungsi panggil balik bergantung pada objek pemancar peristiwa tertentu dan jenis peristiwa Mereka tidak diseragamkan Acara "data" mungkin melepasi objek penimbal data, dan peristiwa "ralat". lulus objek penimbal data Melepasi objek ralat, peristiwa "akhir" aliran data tidak menghantar sebarang data kepada pendengar acara.

Ikat berbilang pendengar acara

Corak pemancar acara membenarkan berbilang pendengar acara mendengar jenis acara yang sama bagi pemancar acara yang sama, seperti:

Salin kod Kod adalah seperti berikut:

Saya mempunyai beberapa data di sini.

Saya juga mempunyai beberapa data di sini.

Pemancar peristiwa bertanggungjawab untuk memanggil semua pendengar terikat pada jenis acara yang ditentukan dalam susunan pendengar didaftarkan, iaitu:

1 Apabila sesuatu peristiwa berlaku, pendengar acara mungkin tidak dipanggil serta-merta.
2. Adalah tingkah laku yang tidak normal untuk pengecualian dilemparkan ke dalam timbunan Ia mungkin kerana terdapat pepijat dalam kod Apabila acara dipancarkan, jika pendengar acara melemparkan pengecualian apabila ia dipanggil, ia mungkin menyebabkan beberapa peristiwa pendengar tidak pernah dipanggil. Dalam kes ini, pemancar peristiwa menangkap pengecualian dan mungkin mengendalikannya.

Lihat contoh ini:

Salin kod Kod adalah seperti berikut:

readStream.on("data", fungsi(data) {

buang Ralat baharu("Sesuatu yang salah telah berlaku");

});

readStream.on("data", fungsi(data) {

console.log('Saya mempunyai beberapa data di sini juga.');

});

Oleh kerana pendengar pertama melemparkan pengecualian, pendengar kedua tidak akan dipanggil.

Alih keluar pendengar acara daripada pemancar acara menggunakan .removeListener()

Jika anda tidak lagi mengambil berat tentang acara objek, anda boleh membatalkan pendengar acara berdaftar dengan menyatakan jenis acara dan fungsi panggil balik, seperti ini:

Salin kod Kod adalah seperti berikut:

fungsi receiveData(data) {

console.log("mendapat data daripada strim baca fail: %j", data);

}

readStream.on("data", receiveData);

// ...

readStream.removeListener("data", receiveData);

Dalam contoh ini, baris terakhir mengalih keluar pendengar peristiwa daripada objek pemancar peristiwa yang boleh dipanggil pada bila-bila masa pada masa hadapan.

Untuk memadamkan pendengar, anda mesti menamakan fungsi panggil balik, kerana nama fungsi panggil balik diperlukan semasa menambah dan mengalih keluar.

Gunakan .once() untuk melaksanakan fungsi panggil balik paling banyak sekali

Jika anda ingin memantau acara yang boleh dilaksanakan paling banyak sekali, atau hanya berminat pada kali pertama peristiwa berlaku, anda boleh menggunakan fungsi .once():

Salin kod Kod adalah seperti berikut:

fungsi receiveData(data) {

console.log("mendapat data daripada strim baca fail: %j", data);

}

readStream.once("data", receiveData);

Dalam kod di atas, fungsi receiveData hanya akan dipanggil sekali. Jika objek readStream memancarkan peristiwa data, fungsi panggil balik receiveData akan dicetuskan sekali sahaja.

Ia sebenarnya hanyalah kaedah kemudahan, kerana ia sangat mudah untuk dilaksanakan, seperti ini:

Salin kod Kod adalah seperti berikut:

var EventEmitter = memerlukan("events").EventEmitter;

EventEmitter.prototype.once = fungsi(jenis, panggil balik) {

var that = this;

this.on(type, function listener() {

that.removeListener(type, listener);

panggil balik.apply(that, arguments);

});

};

Dalam kod di atas, anda mentakrifkan semula fungsi EventEmitter.prototype.once, dan juga mentakrifkan semula fungsi sekali bagi setiap objek yang diwarisi daripada EventEmitter. Kod hanya menggunakan kaedah .on() Setelah acara diterima, ia menggunakan .removeEventListener() untuk membatalkan pendaftaran fungsi panggil balik dan memanggil fungsi panggil balik asal.

Nota: Kaedah function.apply() digunakan dalam kod sebelumnya, yang menerima objek dan menggunakannya sebagai pembolehubah ini yang terkandung, serta tatasusunan parameter. Dalam contoh sebelumnya, tatasusunan parameter yang tidak diubah suai dihantar secara telus ke fungsi panggil balik melalui pemancar peristiwa.

Alih keluar semua pendengar acara daripada pemancar acara menggunakan .removeAllListeners()

Anda boleh mengalih keluar semua pendengar yang didaftarkan pada jenis acara tertentu daripada pemancar acara seperti berikut:

Salin kod Kod adalah seperti berikut:

emitter.removeAllListeners(type);

Sebagai contoh, anda boleh membatalkan semua pendengar isyarat gangguan proses seperti ini:

Salin kod Kod adalah seperti berikut:

process.removeAllListeners("SIGTERM");

Nota: Sebagai peraturan, anda disyorkan hanya menggunakan fungsi ini jika anda tahu apa yang sedang dipadamkan. Jika tidak, anda harus membiarkan bahagian lain aplikasi memadamkan koleksi pendengar acara, atau anda boleh membiarkannya bahagian aplikasi mengambil tanggungjawab untuk diri mereka sendiri. Bagaimanapun, dalam beberapa senario yang jarang berlaku, fungsi ini masih sangat berguna, seperti semasa anda bersiap untuk menutup pemancar peristiwa dengan teratur atau menutup keseluruhan proses.

Buat pemancar peristiwa

Pemancar acara ialah cara yang bagus untuk menjadikan antara muka pengaturcaraan lebih serba boleh Dalam corak pengaturcaraan yang biasa dan mudah difahami, pelanggan secara terus memanggil pelbagai fungsi, manakala dalam corak pemancar acara, pelanggan terikat kepada pelbagai acara, ini akan menjadikan program anda lebih fleksibel. (Nota Penterjemah: Ayat ini tidak begitu yakin, jadi saya menyiarkan teks asal: Pemancar peristiwa menyediakan cara yang bagus untuk menjadikan antara muka pengaturcaraan lebih generik. Apabila anda menggunakan corak yang difahami bersama, pelanggan mengikat peristiwa dan bukannya menggunakan fungsi, menjadikan program anda lebih fleksibel.)

Selain itu, dengan menggunakan pemancar acara, anda juga boleh mendapatkan banyak ciri, seperti mengikat berbilang pendengar yang tidak berkaitan dengan acara yang sama.

Mewarisi daripada pemancar peristiwa Nod

Jika anda berminat dengan corak pemancar acara Node dan merancang untuk menggunakannya dalam aplikasi anda sendiri, anda boleh mencipta kelas pseudo dengan mewarisi EventEmitter:

Salin kod Kod adalah seperti berikut:

util = memerlukan('util');

var EventEmitter = memerlukan('events').EventEmitter;

// Ini ialah pembina MyClass:

var MyClass = function() {

}

util.inherits(MyClass, EventEmitter);

Nota: util.inherits menetapkan rantaian prototaip MyClass supaya contoh MyClass anda boleh menggunakan kaedah prototaip EventEmitter.

Acara pelancaran

Dengan mewarisi daripada EventEmitter, MyClass boleh memancarkan acara seperti ini:

Salin kod Kod adalah seperti berikut:

MyClass.prototype.someMethod = function() {

this.emit("acara tersuai", "hujah 1", "hujah 2");

};

Dalam kod di atas, apabila kaedah someMethod dipanggil oleh contoh MyClass, peristiwa yang dipanggil "acara cuteom" akan dipancarkan juga dua rentetan sebagai data: "argumen 1" dan "argumen 2". , ia akan dihantar sebagai parameter kepada pendengar acara.

Pelanggan contoh MyClass boleh mendengar acara "acara tersuai" seperti ini:

Salin kod Kod adalah seperti berikut:

var myInstance = MyClass();

myInstance.on('acara tersuai', fungsi(str1, str2) {

console.log('mendapat acara tersuai dengan str1 %s dan str2 %s!', str1, str2);

});

Untuk contoh lain, anda boleh membuat kelas Ticker yang mengeluarkan acara "tanda" setiap saat:

Salin kod Kod adalah seperti berikut:

var util = memerlukan('util'),

EventEmitter = memerlukan('events').EventEmitter;

var Ticker = function() {

var self = ini;

setInterval(function() {

self.emit('tanda');

}, 1000);

};

util.inherits(Ticker, EventEmitter);

Pelanggan yang menggunakan kelas Ticker boleh menunjukkan cara menggunakan kelas Ticker dan mendengar acara "tanda",

Salin kod Kod adalah seperti berikut:

var ticker = new Ticker();

ticker.on("tick", function() {

console.log("tandakan");

});

Ringkasan

Corak pemancar peristiwa ialah corak kemasukan semula yang boleh digunakan untuk memisahkan objek pemancar peristiwa daripada set kod khusus peristiwa.

Anda boleh menggunakan event_emitter.on() untuk mendaftarkan pendengar bagi jenis acara tertentu dan event_emitter.removeListener() untuk menyahdaftar.

Anda juga boleh mencipta pemancar acara anda sendiri dengan mewarisi EventEmitter dan hanya menggunakan fungsi .emit().

Kenyataan:
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