Подтвердить что ты не робот

Вызов метода super() внутри Promise: ключевое слово 'super' неожиданно здесь?

Я пытаюсь вызвать супер метод save() из дочернего экземпляра.

// 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
      ...
  }
}

Я получаю сообщение об ошибке:

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

SyntaxError: 'super' keyword unexpected here

Если я перемещаю super.save(filePath, mime); в начале метода save(), он работает.

Я попытался связать контекст с верхней областью:

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

        super.save(filePath, mime);

Но я получаю:

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

Прочитайте этот, но не повезло.

Любые идеи? Спасибо.

окр

[email protected]:/src# node -v
  v4.1.1

docker -v
  Docker version 1.8.2, build 0a8c2e3
4b9b3361

Ответ 1

Похоже, вы обнаружили ошибку при обработке V8 super; Я сообщил об ошибке здесь, и они разделили его как Type-Bug и Priority-Medium. Это подробно рассматривается в нем, в результате чего я опубликовал этот вопрос, где этот ответ подтвердил мою подозрение было ошибкой V8.

Если вы используете функции стрелок (не function) в соответствии с вашим комментарием "Я попытался связать контекст с верхней областью" (основной блок кода использует функцию function, которая не будет работать), он должен работать.

Ожидая исправить, он работает, если вы поместите эту логику в метод:

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

  super.save(filePath, mime);
}

... и вызовите этот метод из обратного вызова обещания:

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

или

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

Это работает, потому что ошибка довольно неясна: она появляется только в том случае, если у вас есть функция стрелки внутри другой функции стрелки внутри метода, а самая внутренняя функция стрелки использует переменную или аргумент, определяемые функцией внешней стрелки (используя материал из сам метод хорош).


Некоторые другие примечания:

  • Если FileKeeper save возвращает обещание, кажется, что ImageKeeper должен использовать это и связывать его. Ваш код просто отбрасывает результат вызова super.save(...).

  • Когда вы обнаруживаете, что пишете new Promise, всегда останавливайтесь и спрашивайте себя, действительно ли этот код является корнем цепочки. Очень, очень, очень часто это не так (и я подозреваю, что это не в вашем коде). Помните, что каждый then возвращает обещание, а мощность promises лежит прежде всего в цепочке. Не нарушайте цепочку, если вам не нужно.