让构造函数返回Promise是不好的做法吗?

我正在尝试为博客平台创建一个构造函数,并且其中包含许多异步操作。这些范围包括从目录中获取帖子,对其进行解析,通过模板引擎发送它们,等等。

所以我的问题是,让我的构造函数返回一个promise而不是调用它们的函数的对象是不明智的new

例如:

var engine = new Engine({path: '/path/to/posts'}).then(function (eng) {
   // allow user to interact with the newly created engine object inside 'then'
   engine.showPostsOnOnePage();
});

现在,用户可能还不提供补充的Promise链接:

var engine = new Engine({path: '/path/to/posts'});

// ERROR
// engine will not be available as an Engine object here

这可能会带来问题,因为用户可能会感到困惑,为什么 engine 在构造后仍然无法使用。

在构造函数中使用Promise的原因很有意义。我希望整个博客在构建阶段之后都能正常运行。但是,调用后立即无法访问该对象似乎有点难闻new

我一直在争论使用类似engine.start().then()engine.init()将返回Promise的方式。但是那些看起来也很臭。

编辑:这在Node.js项目中。

JinJin2020/03/24 19:00:42

为避免关注点分离,请使用工厂创建对象。

class Engine {
    constructor(data) {
        this.data = data;
    }

    static makeEngine(pathToData) {
        return new Promise((resolve, reject) => {
            getData(pathToData).then(data => {
              resolve(new Engine(data))
            }).catch(reject);
        });
    }
}
2020/03/24 19:00:42

构造函数的返回值替换了new运算符刚产生的对象,因此返回promise不是一个好主意。以前,构造函数的显式返回值用于单例模式。

ECMAScript 2017中更好的方法是使用静态方法:您拥有一个进程,这是静态的数字。

构造函数之后在新对象上运行哪种方法可能仅是类本身已知的。要将其封装在类中,可以使用process.nextTick或Promise.resolve,推迟进一步执行,以允许添加侦听器以及在构造函数的调用者Process.launch中进行其他操作。

由于几乎所有代码都在Promise内部执行,因此错误将最终出现在Process.fatal中

可以修改此基本思想以适合特定的封装需求。

class MyClass {
  constructor(o) {
    if (o == null) o = false
    if (o.run) Promise.resolve()
      .then(() => this.method())
      .then(o.exit).catch(o.reject)
  }

  async method() {}
}

class Process {
  static launch(construct) {
    return new Promise(r => r(
      new construct({run: true, exit: Process.exit, reject: Process.fatal})
    )).catch(Process.fatal)
  }

  static exit() {
    process.exit()
  }

  static fatal(e) {
    console.error(e.message)
    process.exit(1)
  }
}

Process.launch(MyClass)