问题 在Promise中调用super()方法:'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

这个,但没有运气。

有任何想法吗?谢谢。

ENV

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

docker -v
  Docker version 1.8.2, build 0a8c2e3

4390
2017-10-04 10:55


起源



答案:


看起来你在V8的处理中发现了一个错误 super;我已经报告了这个错误 这里 他们把它分类为 Type-Bug 和 Priority-Medium。这是在详细研究之后,导致我发布 这个问题,哪里 这个答案 证实了我的怀疑这是一个V8错误。

如果您使用箭头功能(不是 function 函数)按照你的“我已经尝试将绑定上下文绑定到上限”注释(主代码块使用的是 function 它不会起作用的功能 应该 工作。

在等待修复时,如果将该逻辑放在方法中,它会起作用:

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

  super.save(filePath, mime);
}

...并从promise回调中调用该方法:

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)
      })
  })
}

这是有效的,因为这个bug是相当模糊的:如果你有一个箭头功能,它只会出现 另一个 方法内的箭头函数,最里面的箭头函数使用外部箭头函数定义的变量或参数(使用方法本身的东西很好)。


但是其他一些注意事项:

  1. 如果 FileKeepersave 似乎回报了一个承诺 ImageKeeper 应该使用它并链接它。你的代码只是抛弃了调用的结果 super.save(...)

  2. 当你发现自己写作 new Promise,总是停下来问问自己是否有问题的代码  链的根源。非常,非常,经常不是(我怀疑它不在您的代码中)。记住每一个 then 回报承诺,承诺的力量主要在于链条。如果你不需要,不要打破链条。


9
2017-10-04 12:59



谢谢你的深入调查。现在我已经结束了将内部函数移动到单独的函数并应用上下文 this._save.bind(this)。另外,删除了额外的Promise构造函数,谢谢你和@Benjamin花时间指出我的缺陷:)。 - f1nn
@ f1nn:不用担心。这非常有趣,回答这个问题向我证明了我的理解 super 是,嗯,肤浅。 :-)在修复过程中学到了很多东西。 - T.J. Crowder


答案:


看起来你在V8的处理中发现了一个错误 super;我已经报告了这个错误 这里 他们把它分类为 Type-Bug 和 Priority-Medium。这是在详细研究之后,导致我发布 这个问题,哪里 这个答案 证实了我的怀疑这是一个V8错误。

如果您使用箭头功能(不是 function 函数)按照你的“我已经尝试将绑定上下文绑定到上限”注释(主代码块使用的是 function 它不会起作用的功能 应该 工作。

在等待修复时,如果将该逻辑放在方法中,它会起作用:

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

  super.save(filePath, mime);
}

...并从promise回调中调用该方法:

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)
      })
  })
}

这是有效的,因为这个bug是相当模糊的:如果你有一个箭头功能,它只会出现 另一个 方法内的箭头函数,最里面的箭头函数使用外部箭头函数定义的变量或参数(使用方法本身的东西很好)。


但是其他一些注意事项:

  1. 如果 FileKeepersave 似乎回报了一个承诺 ImageKeeper 应该使用它并链接它。你的代码只是抛弃了调用的结果 super.save(...)

  2. 当你发现自己写作 new Promise,总是停下来问问自己是否有问题的代码  链的根源。非常,非常,经常不是(我怀疑它不在您的代码中)。记住每一个 then 回报承诺,承诺的力量主要在于链条。如果你不需要,不要打破链条。


9
2017-10-04 12:59



谢谢你的深入调查。现在我已经结束了将内部函数移动到单独的函数并应用上下文 this._save.bind(this)。另外,删除了额外的Promise构造函数,谢谢你和@Benjamin花时间指出我的缺陷:)。 - f1nn
@ f1nn:不用担心。这非常有趣,回答这个问题向我证明了我的理解 super 是,嗯,肤浅。 :-)在修复过程中学到了很多东西。 - T.J. Crowder