在 Promise 中调用 super() 方法:'super' 关键字在这里意外?

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

我正在尝试从子实例调用超级方法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

如果我在 save() 方法的开头移动 super.save(filePath, mime);,它会起作用。

我试过将上下文绑定到上层范围:

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

阅读 ,但运气不佳。

有什么想法吗?谢谢。

环境

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

docker -v
  Docker version 1.8.2, build 0a8c2e3

您似乎发现了 V8 处理 super 的错误;我已经报告了错误 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 , where 证实了我的怀疑这是一个 V8 错误。

假设您根据您的 "I've tried bind context to upper scope" 评论使用箭头函数(而不是 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)
      })
  })
}

之所以可行,是因为该错误相当隐蔽:只有当您在 另一个 箭头函数中有一个箭头函数时,它才会突然出现在一个方法中,并且最里面的箭头函数使用一个变量或由外部箭头函数定义的参数(使用方法本身的东西很好)。


不过还有一些其他注意事项:

  1. 如果 FileKeepersave returns 是一个承诺,似乎 ImageKeeper 应该使用它并将其链接起来。您的代码只是丢弃了调用 super.save(...).

  2. 的结果
  3. 当你发现自己在写 new Promise 时,总是停下来问问自己,有问题的代码是否真的 链的根。非常非常经常不是(而且我怀疑它不在您的代码中)。请记住,每个 then returns 一个承诺,而承诺的力量主要在于链。没必要不要断链。