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

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

问题描述

我试图为一个博客平台创建一个构造函数,它有许多异步操作。这些范围从抓取目录中的帖子,解析它们,通过模板引擎发送等。



所以我的问题是,让我的构造函数返回是不明智的一个promise,而不是他们称为 new 的函数的对象。



例如:

  var engine = new Engine({path:'/path/to/posts'}).then(function) //允许用户与'then'中新创建的引擎对象交互
engine.showPostsOnOnePage();
});

现在,用户还可以提供补充Promise链接:

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

//错误
//引擎将不可用作引擎对象


b $ b

这可能会造成问题,因为用户可能会感到困惑,为什么 引擎 em>



在构造函数中使用Promise的原因是有意义的。我想让整个博客在施工阶段后运行。但是,在调用 new 之后,似乎气味几乎无法立即访问对象。



讨论使用 engine.start()。then() engine.init()返回Promise。但这些也似乎很臭。



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

解决方案

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



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


如果我想从构造函数执行事情该怎么办?


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

  var engine = new Engine()
engine.displayPosts

如果该任务是异步的,现在可以轻松地从方法中返回一个promise

然而,当方法(异步)改变实例并且其他方法依赖于该方法时,我不推荐使用此模式,因为这将导致它们需要等待(变为异步即使它们实际上是同步的),你很快会有一些内部队列管理。


如果要将数据异步加载到实例中,该怎么办?

$问自己:你真的需要没有数据的实例吗?



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



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

  Engine.load({path:'/ path /到/ posts'})然后(function(posts){
new Engine(posts).displayPosts();
});

这样可以更灵活地获取数据,并简化构造函数。类似地,您可以编写返回 Engine 实例的承诺的静态工厂函数:

  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框架).then(function(framePage){
engine.showPostsOn(framePage);
});
});


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.

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.

For instance:

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

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

This could pose a problem as the user may be confused why engine is not available after construction.

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.

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.

Edit: This is in a Node.js project.

解决方案

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?

Ask yourself: Do you actually need the instance without the data? Could you use it somehow?

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

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

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天全站免登陆