让构造函数返回 Promise 是不好的做法吗? [英] Is it bad practice to have a constructor function return a Promise?

查看:31
本文介绍了让构造函数返回 Promise 是不好的做法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为博客平台创建一个构造函数,它在内部进行了许多异步操作.这些包括从目录中抓取帖子、解析它们、通过模板引擎发送它们等等.

I'm trying to create a constructor for a blogging platform and it has many async operations going on inside. These range from grabbing the posts from directories, parsing them, sending them through template engines, etc.

所以我的问题是,让我的构造函数返回一个承诺而不是他们调用 new 的函数的对象是否是不明智的.

So my question is, would it be unwise to have my constructor function return a promise instead of an object of the function they called new against.

例如:

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 链链接:

Now, the user may also not supply a supplement Promise chain link:

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

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

这可能会造成问题,因为用户可能会困惑为什么 engine 在构建后不可用.

在构造函数中使用 Promise 的原因是有道理的.我希望整个博客在构建阶段后都能正常运行.但是,在调用 new 后几乎无法立即访问该对象似乎是一种气味.

The reason to use a Promise in the constructor makes sense. I want the entire blog to be functioning after the construction phase. However, it seems like a smell almost to not have access to the object immediately after calling new.

我曾讨论过使用 engine.start().then()engine.init() 之类的东西,它们会返回 Promise.但那些看起来也很臭.

I have debated using something along the lines of engine.start().then() or engine.init() which would return the Promise instead. But those also seem smelly.

这是在 Node.js 项目中.

This is in a Node.js project.

推荐答案

是的,这是一个糟糕的做法.构造函数应该返回它的类的一个实例,没有别的.它会弄乱 new 运算符否则继承.

Yes, it is a bad practise. A constructor should return an instance of its class, nothing else. It would mess up the new operator and inheritance otherwise.

此外,构造函数应该只创建和初始化一个新实例.它应该设置数据结构和所有特定于实例的属性,但不执行任何任务.如果可能,它应该是一个纯函数,没有副作用,具有所有优点.

Moreover, a constructor should only create and initialize a new instance. It should set up data structures and all instance-specific properties, but not execute any tasks. It should be a pure function without side effects if possible, with all the benefits that has.

如果我想从我的构造函数中执行东西怎么办?

What if I want to execute things from my constructor?

这应该在你的类的方法中.你想改变全局状态吗?然后显式调用该过程,而不是作为生成对象的副作用.这个调用可以在实例化之后立即进行:

That should go in a method of your class. You want to mutate global state? Then call that procedure explicitly, not as a side effect of generating an object. This call can go right after the instantiation:

var engine = new Engine()
engine.displayPosts();

如果该任务是异步的,您现在可以轻松地从该方法返回其结果的承诺,以轻松等待它完成.
然而,当方法(异步)改变实例而其他方法依赖于它时,我不会推荐这种模式,因为这会导致它们被要求等待(即使它们实际上是同步的也变成异步)并且你很快就会有正在进行一些内部队列管理.不要将实例编码为存在但实际上无法使用.

If that task is asynchronous, you can now easily return a promise for its results from the method, to easily wait until it is finished.
I would however not recommend this pattern when the method (asynchronously) mutates the instance and other methods depend on that, as that would lead to them being required to wait (become async even if they're actually synchronous) and you'd quickly have some internal queue management going on. Do not code instances to exist but be actually unusable.

如果我想将数据异步加载到我的实例中怎么办?

What if I want to load data into my instance asynchronously?

问问自己:你真的需要没有数据的实例吗?你能以某种方式使用它吗?

如果答案是,那么您不应该在拥有数据之前创建它.将数据 ifself 作为构造函数的参数,而不是告诉构造函数如何获取数据(或传递数据的承诺).

If the answer to that is No, then you should not create it before you have the data. Make the data ifself a parameter to your constructor, instead of telling the constructor how to fetch the data (or passing a promise for the data).

然后,使用静态方法加载数据,从中返回一个promise.然后链接一个将数据包装在一个新实例中的调用:

Then, use a static method to load the data, from which you return a promise. Then chain a call that wraps the data in a new instance on that:

Engine.load({path: '/path/to/posts'}).then(function(posts) {
    new Engine(posts).displayPosts();
});

这在获取数据的方式上提供了更大的灵活性,并大大简化了构造函数.类似地,您可以编写静态工厂函数,为 Engine 实例返回承诺:

This allows much greater flexibility in the ways to acquire the data, and simplifies the constructor a lot. Similarly, you might write static factory functions that return promises for Engine instances:

Engine.fromPosts = function(options) {
    return ajax(options.path).then(Engine.parsePosts).then(function(posts) {
        return new Engine(posts, options);
    });
};

…

Engine.fromPosts({path: '/path/to/posts'}).then(function(engine) {
    engine.registerWith(framework).then(function(framePage) {
        engine.showPostsOn(framePage);
    });
});

这篇关于让构造函数返回 Promise 是不好的做法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆