corvid
corvid

Reputation: 11187

Implementation of chained es6 promises within a class

I'm a bit confused by the context of this in es6 promises. Here is some code that handles async functions with Promise.

/**
* Generic recreation of apple photobooth on electron (javascript practice)
*/
class Photobooth {
  constructor(height=320, width=320) {
    this._height = 320;
    this._width = 320;
    this.video = video ? $(video) : $(document.createElement('video'));
  }
  getStream() {
    return new Promise(function (resolve, reject) {
      return navigator.webkitGetUserMedia({ video: true }, resolve, reject);
    });
  }
  streamTo(stream, element) {
    element.appendChild(self.video);
    var self = this;
    return new Promise(function (resolve, reject) {
      self.video.attr('src', window.URL.createObjectUrl(stream));
      self.video.on('loadedmetadata', function () {
        self.video.get(0);
        resolve();
      });
    });
  }
}

I want to implement chaining to look something like as follows.

Photobooth
  .getStream()
  .streamTo(document.body);

Lodash has a similar feature with chaining.

// gets sorted scores for class.
_([
  { name: 'Jeff', scores: [0.78, 0.85] },
  { name: 'Jessica', scores: [0.84, 0.68] },
  { name: 'Tim', scores: [0.92, 0.67] }
])
  .pluck('scores')
  .flatten()
  .map(x => x * 100)
  .sortBy()
  .value();

How can this be class-based promise-chaining be implemented in javascript?

Upvotes: 0

Views: 441

Answers (1)

Bergi
Bergi

Reputation: 664297

I'm a bit confused by the context of this in es6 promises

There's nothing special about promises, this works as always. With ES6, it does simplify things to use arrow functions for the promise callbacks.

I want to implement chaining

Currently your functions do return promises, which do chain albeit with then. For custom chaining, like underscore does it, you will have to wrap your data (in this case, the promises) in your custom objects that have the methods that you want.

In your specific case, you might however not use that getStream method at all, it seems to be the only purpose of your PhotoBoth instances so you can put it right into the constructor. I would do

class Photobooth {
  constructor(video=document.createElement('video'), height=320, width=320) {
    this._height = 320;
    this._width = 320;
    this.video = $(video);
    this.initStream()
  }
  initStream() {
    this.stream = new Promise((resolve, reject) =>
      navigator.webkitGetUserMedia({video: true}, resolve, reject);
    );
  }
  streamTo(element) {
    this.video.appendTo(element);
    return this.stream.then((stream) => new Promise((resolve, reject) => {
      this.video.prop('src', window.URL.createObjectUrl(stream));
      this.video.on('loadedmetadata', function(e) {
        resolve(this);
      });
    }), (err) => {
      $(element).text("Failed to get stream");
      throw err;
    });
  }
}

Upvotes: 1

Related Questions