Node Events 1 – Basic Usage

Node in Practice 第四章 – EventsEmitter – Basic Usage。


在基础用法中,可分为两种:

1. 继承 EventEmitter

除了可以采用 Node 的 util.inherits 方法以外,还可以采用 ES5 的 Object.create。utils.inherits 与 Ojbect.create 相比,除了深度复制 prototypes 以外,还指明父类构造函数 super_。

这种方式将 EventEmitter 继承下来,即可使用 on、once、emit、removeListener 等方法,为 is-a 使用模式。

2. Mixing EventEmitter

与 EventEmitter merge,只拷贝一层我们需要的 prototypes,这种使用方式与 has-a 使用模式比较接近。

参考:

  1. Alex Young, Marc Harter. Node in Practice. 2015
// Node in practice 4.1

// 1. Inheriting from EventEmitter
;(function () {
  'use strict';

  ;const MusicPlayer = (function () {

    const util = require('util');
    const events = require('events');
    const AudioDevice = {
      play () {
        // Stub: Trigger playback throught iTunes, mpg123, etc.
      },

      stop () { }
    };

    const self = { };

    const $ = function (track) {
      events.EventEmitter.call(this);

      self.track = track;
      self.palying = false;
      self.audioFirstStarted = undefined;
    }

    util.inherits($, events.EventEmitter);

    $.prototype.play = function () {
      self.playing = true;
      self.audioFirstStarted = new Date();
      AudioDevice.play();
    };

    $.prototype.stop = function () {
      self.playing = false;
      AudioDevice.stop();
    };

    $.prototype.playOnce = function () {
      self.playing = true;
      !self.audioFirstStarted && (self.audioFirstStarted = new Date());
      AudioDevice.play();
    };

    $.prototype.toString = function () {
      return self.playing &&
        `Now playing: ${self.track} (${self.audioFirstStarted})` ||
        'Stopped';
    };

    return $;
  }());

  // The demo usage:
  const musicPlayer = new MusicPlayer('The Roots - The Fire');

  // musicPlayer.on('play', function () {
  //   this.play();
  //   console.log(this.toString());
  // });

  musicPlayer.once('play', function (track) {
    this.playOnce();
    console.log(this.toString());
  });

  musicPlayer.on('stop', function () {
    this.stop();
    console.log(this.toString());
  });

  musicPlayer.emit('play');
  musicPlayer.emit('play');

  setTimeout(() => {
    musicPlayer.emit('stop')
  }, 1000);
}());


// 2. Mixing in EventEmitter
// NOTE: This technique may be useful when you already have a well-established
//       class that could benefit from events, but can’t easily be a direct 
//       descendant of EventEmitter.
;(function () {
  'use strict';

  ;const MusicPlayer = (function () {

    const { EventEmitter } = require('events');

    // Mixing tow objects
    const merge = (a, b) => {
      if (a && b) for (const key in b) a[key] = b[key];
      return a;
    };

    const self = { };

    const $ = function (track) {
      self.track = track;
      self.palying = false;

      merge(this, EventEmitter.prototype);
    };

    util.inherits($, events.EventEmitter);

    $.prototype.play = function () { self.playing = true; };

    $.prototype.stop = function () { self.playing = false; };

    $.prototype.toString = function () {
      return self.playing &&
        `Now playing: ${self.track}` ||
        'Stopped';
    };

    return $;
  }());

  // The demo usage:
  const musicPlayer = new MusicPlayer('Girl Talk - Stil Here');

  musicPlayer.on('play', function () {
    this.play();
    console.log(this.toString());
  });

  musicPlayer.on('stop', function () {
    this.stop();
    console.log(this.toString());
  });

  musicPlayer.emit('play');

  setTimeout(() => {
    musicPlayer.emit('stop')
  }, 1000);
}());

作者: V

Web Dev

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s