Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling super() method inside Promise: 'super' keyword unexpected here?

I'm trying to call super method save() from child instance.

// ImageKeeper.js
'use strict';

module.exports = class ImageKeeper extends FileKeeper {
  constructor(keeperPath, options) {
    super(`/${keeperPath}`, options)
    this.keeperPath = keeperPath;
  }

  save(filePath) {
    return new Promise((resolve, reject) => {
      this
        .resolvePath(filePath)
        .then(function(fileData) {
          var filePath = fileData[0],
            mime = fileData[1];

          super.save(filePath, mime); // <-- GETTING ERROR HERE
        })
        .catch(function(err) {
          reject(err)
        })
    })
  }
}

// FileKeeper.js
'use strict';

module.exports = class FileKeeper {
  constructor(keeperPath, options) {
    this.storagePath = path.resolve(`${env.paths.storage}${keeperPath}`);
    this.options = options;
  }

  save(filePath, mime) {
    return Promise
      ...
  }
}

I'm getting error:

/src/filekeeper/imagekeeper.js:110
          super.save(filePath, mime);
          ^^^^^

SyntaxError: 'super' keyword unexpected here

If I move super.save(filePath, mime); in the beginning of save() method, it works.

I've tried bind context to upper scope:

save(filePath) {
  return new Promise((resolve, reject) => {
    this
      .then((fileData) => { // <-- bind context to upper scope

        super.save(filePath, mime);

But I'm getting:

Unhandled rejection SyntaxError: 'super' keyword unexpected here
    at processImmediate [as _immediateCallback] (timers.js:374:17)
From previous event:
    at /src/filekeeper/imagekeeper.js:106:10

Read this, but no luck.

Any ideas? Thank you.

env

root@8d1024b233c3:/src# node -v
  v4.1.1

docker -v
  Docker version 1.8.2, build 0a8c2e3
like image 206
f1nn Avatar asked Oct 04 '15 10:10

f1nn


People also ask

Which statement is true about super () method?

0 super keyword is used to invoke immediate parent class method All the given options are correct super() is used to invoke immediate parent class constructor .

What does super () do in JS?

The super keyword is used to access properties on an object literal or class's [[Prototype]], or invoke a superclass's constructor. The super. prop and super[expr] expressions are valid in any method definition in both classes and object literals.

What does a call to super () accomplish?

The super keyword is used to call the constructor of its parent class to access the parent's properties and methods.

What is super () in angular?

super is ES6 syntax that cannot be used outside the method where it's used. Given there is Foo class that extends Bar , super keyword is interpreted as Bar in Foo constructor and static methods and as Bar.


1 Answers

Looks like you've found a bug in V8's handling of super; I've reported the bug here and they've triaged it as Type-Bug and Priority-Medium. This is after looking into it in some detail, resulting in my posting this question, where this answer confirmed my suspicion it was a V8 bug.

Provided you use arrow functions (not function functions) as per your "I've tried bind context to upper scope" comment (the main code block is using a function function, which won't work), it should be working.

While waiting for a fix, it works if you put that logic in a method:

someAppropriateName(fileData) {
  var filePath = fileData[0],
    mime = fileData[1];

  super.save(filePath, mime);
}

...and call that method from the promise callback:

save(filePath) {
  return new Promise((resolve, reject) => {
    this
      .resolvePath(filePath)
      .then(fileData => {                      // **
          this.someAppropriateName(fileData);  // **
      })                                       // **
      .catch(function(err) {
        reject(err)
      })
  })
}

or:

save(filePath) {
  return new Promise((resolve, reject) => {
    this
      .resolvePath(filePath)
      .then(this.someAppropriateName.bind(this)) // **
      .catch(function(err) {
        reject(err)
      })
  })
}

That works because the bug is fairly obscure: It only crops up if you have an arrow function inside another arrow function inside a method, and the innermost arrow function uses a variable or argument defined by the outer arrow function (using stuff from the method itself is fine).


Some other notes, though:

  1. If FileKeeper's save returns a promise, it seems like ImageKeeper should be using that and chaining off it. Your code just throws away the result of calling super.save(...).

  2. When you find yourself writing new Promise, always stop and ask yourself if the code in question is really the root of the chain. Very, very, very often it isn't (and I suspect it isn't in your code). Remember that every then returns a promise, and the power of promises lies primarily in the chain. Don't break the chain if you don't have to.

like image 107
T.J. Crowder Avatar answered Sep 20 '22 22:09

T.J. Crowder