নোড.জেএস - ইভেন্টইমিটারের উত্তরাধিকারসূত্রে


89

আমি বেশ কয়েকটি নোড.জেএস লাইব্রেরিতে এই প্যাটার্নটি দেখছি:

Master.prototype.__proto__ = EventEmitter.prototype;

(উত্স এখানে )

কেউ দয়া করে আমাকে একটি উদাহরণ দিয়ে ব্যাখ্যা করতে পারেন, কেন এটি এত সাধারণ প্যাটার্ন এবং এটি কার্যকর যখন?


তথ্যের জন্য এই প্রশ্নটি দেখুন stackoverflow.com/questions/5398487/…
রসালো স্ক্রিপ্টার

14
নোটটি __proto__একটি অ্যান্টি-প্যাটার্ন, দয়া করে ব্যবহার করুনMaster.prototype = Object.create(EventEmitter.prototype);
রায়নোস

69
আসলে, ব্যবহার করুনutil.inherits(Master, EventEmitter);
থেমসার্ট

4
@ রায়নোস একটি অ্যান্টি-প্যাটার্ন কী?
স্টারবিয়াম্রেনবোলাব

4
এটি এখন ES6 বর্গ নির্মাণকারীদের সাথে আরও সহজ easier এখানে কমপ্যাট পরীক্ষা করুন: kangax.github.io/compat-table/es6 । ডক্স বা নীচে আমার উত্তর পরীক্ষা করুন।
শৈশবে

উত্তর:


84

কোডটির উপরের মতামতটি যেমন বলেছে, এটি Masterউত্তরাধিকার সূত্রে প্রাপ্ত হবে EventEmitter.prototype, সুতরাং আপনি ইভেন্টটি নির্গত করতে এবং শুনতে এই 'শ্রেণীর' উদাহরণ ব্যবহার করতে পারেন।

উদাহরণস্বরূপ আপনি এখন এটি করতে পারেন:

masterInstance = new Master();

masterInstance.on('an_event', function () {
  console.log('an event has happened');
});

// trigger the event
masterInstance.emit('an_event');

আপডেট : যতগুলি ব্যবহারকারী চিহ্নিত করেছেন, নোডে এটি করার 'মানক' উপায়টি হ'ল 'ইউট.ইন.ইরিটিস' ব্যবহার করা হবে:

var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);

২ য় আপডেট : ES6 ক্লাস নিয়ে আমাদের উপর, EventEmitterএখন ক্লাসটি বাড়ানোর পরামর্শ দেওয়া হচ্ছে :

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

myEmitter.on('event', () => {
  console.log('an event occurred!');
});

myEmitter.emit('event');

Https://nodejs.org/api/events.html#events_events দেখুন


4
(শুধু একটু অনুস্মারক করতে require('events').EventEmitterপ্রথম করতে আমি সবসময় ভুলবেন এখানে কেস অন্য কেউ এটা চাহিদা মধ্যে ডক্সে লিঙ্ক। nodejs.org/api/events.html#events_class_events_eventemitter )
mikermcneil

4
বিটিডাব্লু, উদাহরণগুলির জন্য সম্মেলনটি হ'ল প্রথম চিঠিটি ছোট করে রাখা MasterInstanceউচিত , তাই হওয়া উচিত masterInstance
খোমিস্টার

এবং আপনি কীভাবে চেক করার ক্ষমতা বজায় রাখবেন: মাস্টার ইনস্ট্যান্স উদাহরণস্বরূপ?
জয়য়ারজো

4
util.inheritssuper_সম্পত্তি Masterবস্তুর মধ্যে ইনজেকশনের একটি বাজে কাজ করে । এটি অপ্রয়োজনীয় এবং প্রোটোটাইপিকাল উত্তরাধিকারকে ক্লাসিক উত্তরাধিকারের মতো আচরণ করার চেষ্টা করে। ব্যাখ্যার জন্য এই পৃষ্ঠার নীচে একবার দেখুন ।
klh

4
শুধু @loretoparisi Master.prototype = EventEmitter.prototype;। সুপারের দরকার নেই। আপনি ES6 এক্সটেন্ডসগুলি (এবং এটি নোড.জেএস ডক্সে উত্সাহিত করা util.inherits) এর মতো ব্যবহার class Master extends EventEmitterকরতে পারেন - আপনি ক্লাসিকাল হন super()তবে কোনও কিছুতে ইনজেকশন না দিয়ে Master
klh

81

ES6 স্টাইল শ্রেণীর উত্তরাধিকার

নোড ডকস এখন আপনার নিজের ইভেন্ট প্রেরক তৈরির জন্য শ্রেণি উত্তরাধিকার ব্যবহারের পরামর্শ দেয় :

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {
  // Add any custom methods here
}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

দ্রষ্টব্য: আপনি যদি কোনও constructor()ফাংশনটি সংজ্ঞায়িত করেন তবে পিতা-মাতার শ্রেণীর নির্মাতাটিকেও MyEmitterডাকা super()হবে তা নিশ্চিত করার জন্য আপনাকে এটিকে কল করা উচিত , যদি না আপনি যদি না চান তবে ভাল কারণ নেই।


9
এই মন্তব্যগুলি সঠিক নয় এবং এক্ষেত্রে বিভ্রান্তিকর হচ্ছে। কলিং super()হয় প্রয়োজন নেই , যতদিন আপনি প্রয়োজন নেই যেমন / একটি কন্সট্রাকটর নির্ধারণ করুন, অত: পর Breedly মূল উত্তর (সম্পাদনা ইতিহাস দেখুন) সম্পূর্ণভাবে সঠিক ছিল। এই ক্ষেত্রে আপনি এই একই উদাহরণটিকে অনুলিপিতে অনুলিপি করতে এবং কাস্ট করতে পারেন, নির্মাতাকে পুরোপুরি সরান এবং এটি একইভাবে কাজ করবে। এটি পুরোপুরি বৈধ সিনট্যাক্স।
অরেলিও

39

অন্য জাভাস্ক্রিপ্ট অবজেক্ট থেকে উত্তরাধিকারী হওয়ার জন্য, বিশেষত নোড.জেসের ইভেন্টইমিটার তবে সাধারণভাবে কোনও বস্তু, আপনার দুটি জিনিস করতে হবে:

  • আপনার অবজেক্টের জন্য একটি কনস্ট্রাক্টর সরবরাহ করুন, যা পুরোপুরি অবজেক্টটি আরম্ভ করে; আপনি অন্য কোনও অবজেক্ট থেকে উত্তরাধিকারী হচ্ছেন এমন ক্ষেত্রে আপনি সম্ভবত এই আরম্ভের কিছু কাজ সুপার কনস্ট্রাক্টরকে অর্পণ করতে চান।
  • এমন একটি প্রোটোটাইপ অবজেক্ট সরবরাহ করুন যা [[proto]]আপনার কনস্ট্রাক্টর থেকে তৈরি বস্তুর জন্য ব্যবহৃত হবে ; আপনি অন্য কোনও অবজেক্ট থেকে উত্তরাধিকার সূত্রে প্রাপ্ত ক্ষেত্রে আপনি সম্ভবত অন্য বিষয়টির উদাহরণটি আপনার প্রোটোটাইপ হিসাবে ব্যবহার করতে চান।

এটি জাভাস্ক্রিপ্টে আরও জটিল কারণ এটি অন্য ভাষাগুলির চেয়ে বেশি বলে মনে হচ্ছে কারণ

  • জাভাস্ক্রিপ্ট বস্তুর আচরণকে "কনস্ট্রাক্টর" এবং "প্রোটোটাইপ" -র মধ্যে পৃথক করে। এই ধারণাগুলি একসাথে ব্যবহার করার জন্য বোঝানো হয়েছে তবে আলাদাভাবে ব্যবহার করা যেতে পারে।
  • জাভাস্ক্রিপ্ট একটি খুব ত্রুটিযুক্ত ভাষা এবং লোকেরা এটি আলাদাভাবে ব্যবহার করে এবং "উত্তরাধিকার" অর্থ কী, তার একক প্রকৃত সংজ্ঞা নেই।
  • অনেক ক্ষেত্রে, আপনি সঠিক কিসের একটি উপসেটটি দিয়ে পালিয়ে যেতে পারেন, এবং অনুসরণ করার জন্য আপনি প্রচুর উদাহরণ পাবেন (এই SO প্রশ্নের কিছু অন্যান্য উত্তর সহ) যা আপনার ক্ষেত্রে সার্থক বলে মনে হচ্ছে।

নোড.জেএস এর ইভেন্টইমিটারের নির্দিষ্ট কেসের জন্য, এখানে কী কাজ করে তা এখানে:

var EventEmitter = require('events').EventEmitter;
var util = require('util');

// Define the constructor for your derived "class"
function Master(arg1, arg2) {
   // call the super constructor to initialize `this`
   EventEmitter.call(this);
   // your own initialization of `this` follows here
};

// Declare that your class should use EventEmitter as its prototype.
// This is roughly equivalent to: Master.prototype = Object.create(EventEmitter.prototype)
util.inherits(Master, EventEmitter);

সম্ভাব্য ফেবিল:

  • আপনি যদি আপনার সাবক্লাসের জন্য প্রোটোটাইপ (মাস্টার.প্রোটোটাইপ) ব্যবহার করে বা ব্যবহার না করে ব্যবহার করেন util.inheritsতবে EventEmitterআপনার শ্রেণীর উদাহরণের জন্য সুপার কনস্ট্রাক্টরকে ( ) কল করবেন না , সেগুলি সঠিকভাবে আরম্ভ করা হবে না।
  • আপনি যদি সুপার কনস্ট্রাক্টরকে কল করেন তবে প্রোটোটাইপ সেট না করেন, ইভেন্টইমিটার পদ্ধতিগুলি আপনার অবজেক্টে কাজ করবে না
  • আপনি সুপারক্লাস (একজন সক্রিয়া উদাহরণস্বরূপ ব্যবহার করার চেষ্টা করতে পারে new EventEmitterহিসাবে) Master.prototypeপরিবর্তে উপশ্রেণী কন্সট্রাকটর থাকার Masterসুপার কন্সট্রাকটর কল EventEmitter; সুপারক্লাস নির্মাণকারীর আচরণের উপর নির্ভর করে যা মনে হতে পারে এটি কিছুক্ষণ ঠিকঠাক কাজ করছে তবে একই জিনিস নয় (এবং ইভেন্টেমিটারের জন্য কাজ করবে না)।
  • আপনি Master.prototype = EventEmitter.prototypeঅবজেক্ট.ক্রিয়েটের মাধ্যমে অবজেক্টের অতিরিক্ত স্তর যুক্ত করার পরিবর্তে সরাসরি সুপার প্রোটোটাইপ ব্যবহার করার চেষ্টা করতে পারেন ; এটি মনে হচ্ছে এটি ঠিকঠাক কাজ করছে যতক্ষণ না কেউ আপনার বস্তুকে Masterবানকিপ্যাচ করে EventEmitterএবং অজান্তে বাঁদিক এবং তার সমস্ত বংশধরদেরও না করে। প্রতিটি "শ্রেণি" এর নিজস্ব প্রোটোটাইপ থাকা উচিত।

আবার: ইভেন্টইমিটার (বা সত্যিকারের কোনও বিদ্যমান বস্তু "শ্রেণি") থেকে উত্তরাধিকারী হওয়ার জন্য, আপনি এমন একটি নির্মাতার সংজ্ঞা দিতে চান যা সুপার কনস্ট্রাক্টরকে চেইন করে এবং একটি প্রোটোটাইপ সরবরাহ করে যা সুপার প্রোটোটাইপ থেকে প্রাপ্ত।


19

এইভাবে জাভাস্ক্রিপ্টে প্রোটোটাইপিকাল (প্রোটোটাইপাল?) উত্তরাধিকার সম্পন্ন হয়। এমডিএন থেকে :

অবজেক্টের প্রোটোটাইপ বোঝায়, যা কোনও বস্তু বা নাল হতে পারে (যার অর্থ সাধারণত অবজেক্টটি অবজেক্ট.প্রোটোটাইপ, যার কোনও প্রোটোটাইপ নেই)। এটি কখনও কখনও প্রোটোটাইপ-উত্তরাধিকার ভিত্তিক সম্পত্তি অনুসন্ধানগুলি প্রয়োগ করতে ব্যবহৃত হয়।

এটি পাশাপাশি কাজ করে:

var Emitter = function(obj) {
    this.obj = obj;
}

// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);

জাভা স্ক্রিপ্ট বোঝা ওওপি ECMAScript 5-তে আমি ওপিতে ইদানীং পড়ি এমন সেরা নিবন্ধগুলির মধ্যে একটি।


7
Y.prototype = new X();একটি অ্যান্টি-প্যাটার্ন, দয়া করে ব্যবহার করুনY.prototype = Object.create(X.prototype);
রায়নোস

এটা জানা ভালো. আমি কি আরও কোথাও পড়তে পারি? ফলাফলগুলি কীভাবে পৃথক হবে সে বিষয়ে আগ্রহী interested
ড্যাফ

4
new X()একটি দৃষ্টান্ত ইনস্ট্যান্টিয়েট করুন X.prototypeএবং এটিতে অনুরোধ করে এটি সূচনা Xকরুন। Object.create(X.prototype)কেবল একটি উদাহরণ ইনস্ট্যান্ট করে তোলে। আপনি Emitter.prototypeআরম্ভ করতে চান না । আমি এটির একটি ভাল নিবন্ধ খুঁজে পাই না।
রায়নোস

এইবার বুঝতে পারছি. এটা ইশারা জন্য ধন্যবাদ। নোডে এখনও ভাল অভ্যাসে প্রবেশ করার চেষ্টা করছি। ব্রাউজারগুলি কেবল ইসিএমএ 5 এর জন্য নেই (এবং আমি বুঝতে পারি যে শিমটি সবচেয়ে নির্ভরযোগ্য নয়)।
ড্যাফ

4
অন্য লিঙ্কটিও ভেঙে গেছে। এটি ব্যবহার করে দেখুন: রোবটলোলিটা.github.io/2011/10/09/…
jlukanta

5

আমি ভেবেছিলাম http://www.bennadel.com/blog/2187- এক্সটেন্ডিং- ইভেন্টএমিটার- টো- ক্রিয়েট- অ্যাভেনডেড- ক্যাশে-ইন- নোড- জেএসএসটিএম থেকে এই পদ্ধতিটি বেশ ঝরঝরে ছিল:

function EventedObject(){

  // Super constructor
  EventEmitter.call( this );

  return( this );

}

ডগলাস ক্রকফোর্ডেরও কিছু আকর্ষণীয় উত্তরাধিকারের নিদর্শন রয়েছে: http://www.crockford.com/javascript/inheritance.html

আমি খুঁজে পেয়েছি জাভাস্ক্রিপ্ট এবং নোড.জেএস এ উত্তরাধিকারের কম প্রয়োজন হয়। তবে একটি অ্যাপ্লিকেশন লেখার ক্ষেত্রে যেখানে উত্তরাধিকার স্কেলেবিলিটিতে প্রভাব ফেলতে পারে, আমি রক্ষণাবেক্ষণের বিরুদ্ধে কর্মক্ষমতা ওজন বিবেচনা করব। অন্যথায়, আমি কেবলমাত্র আমার সিদ্ধান্তটিকে ভিত্তি করব যার ভিত্তিতে নিদর্শনগুলি আরও ভাল সামগ্রিক নকশাগুলির দিকে পরিচালিত করে, আরও রক্ষণাবেক্ষণযোগ্য এবং কম ত্রুটি-প্রবণ one

মোটামুটি তুলনা পেতে গুগল ক্রোম (ভি 8) ব্যবহার করে জেএসফুরে বিভিন্ন নিদর্শনগুলি পরীক্ষা করুন। ভি 8 হ'ল জাভাস্ক্রিপ্ট ইঞ্জিন যা নোড.জেএস এবং ক্রোম উভয়ই ব্যবহার করে।

আপনাকে শুরু করার জন্য এখানে কিছু jscreens রয়েছে:

http://jsperf.com/prototypees-vs-funitions/4

http://jsperf.com/inheritance-proto-vs-object-create

http://jsperf.com/inheritance-perf


4
আমি এই পদ্ধতির এবং উভয় চেষ্টা করেছি emitএবং onযেমন undefined উত্ক্রান্ত করছে।
দোপতরমন

প্রত্যাবর্তন (এই) নয়; শুধু শিকল দেওয়ার জন্য?
বুলেব্লা

1

ডাব্লুপিআরএল এর প্রতিক্রিয়া যোগ করতে। তিনি "প্রোটোটাইপ" অংশটি মিস করেছেন:

function EventedObject(){

   // Super constructor
   EventEmitter.call(this);

   return this;

}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part

4
প্রকৃতপক্ষে, আপনার পরিবর্তে নতুনের পরিবর্তে অবজেক্ট.ক্রেট ব্যবহার করা উচিত অন্যথায় আপনি উদাহরণের অবস্থা এবং অন্য কোথাও বর্ণিত প্রোটোটাইপে আচরণ পাবেন । তবে ইএস use এবং ট্রান্সপাইল ব্যবহার করা আরও ভাল বা util.inheritsযেহেতু প্রচুর স্মার্ট ব্যক্তি আপনার পক্ষে সেই বিকল্পগুলি আপ টু ডেট রাখবে।
শীতল নীল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.