1. ホーム
  2. javascript

[解決済み] コンストラクタ関数が Promise を返すのは悪い習慣ですか?

2022-04-20 20:33:32

質問

ブログプラットフォーム用のコンストラクタを作成しようとしていますが、内部で多くの非同期処理が行われています。これらは、ディレクトリから投稿を取得し、それらを解析し、テンプレートエンジンを介してそれらを送信するなど、多岐にわたります。

そこで質問なのですが、コンストラクタの関数が、呼び出した関数のオブジェクトではなく、プロミスを返すようにすることは賢明ではないのでしょうか? 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();
});

さて、ユーザーは次のようなこともできます。 ない 補足 プロミスチェーンリンクを供給する。

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() を使えば、代わりにプロミスを返します。しかし、これらも胡散臭く感じます。

編集:これはNode.jsのプロジェクトでの話です。

解決方法は?

そう、これは悪い習慣なのです。コンストラクタはそのクラスのインスタンスを返すべきで、それ以外のものを返してはいけません。これは new 演算子 であり、それ以外は継承される。

さらに、コンストラクタは新しいインスタンスの作成と初期化のみを行う必要があります。データ構造とインスタンス固有のプロパティをすべてセットアップする必要がありますが 実行しない タスクを実行します。それは 純粋関数 可能であれば副作用を排除し、そのメリットを享受してください。

コンストラクタから実行したい場合はどうすればいいですか?

それはあなたのクラスのメソッドに入れるべきです。グローバルな状態を変化させたいのですか?それなら、オブジェクト生成の副作用としてではなく、明示的にそのプロシージャを呼び出します。この呼び出しは、インスタンス化の直後に行うことができます。

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

そのタスクが非同期であれば、メソッドからその結果のプロミスを返すことで、簡単に終了まで待つことができるようになりました。

しかし、このパターンは、メソッドが(非同期に)インスタンスを変異させ、他のメソッドがそれに依存する場合にはお勧めしません。なぜなら、他のメソッドは待つことを要求され(実際には同期であっても非同期になる)、すぐに内部キュー管理が行われることになるからです。インスタンスが存在しても、実際には使用できないようなコーディングはしないでください。

<ブロッククオート

データを非同期でインスタンスにロードしたい場合はどうすればよいですか?

自問自答してください。 データ無しのインスタンスが実際に必要ですか?どうにかして使うことはできないか?

もし、その答えが いいえ であれば、データが揃う前に作成するべきではありません。データを取得する方法をコンストラクタに指示する(あるいはデータのプロミスを渡す)のではなく、データ自身をコンストラクタのパラメータにするのです。

次に、静的メソッドを使用してデータをロードし、そこからプロミスを返します。そして、データを新しいインスタンスにラップする呼び出しを、その上でチェーンさせます。

Engine.load({path: '/path/to/posts'}).then(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(framework).then(function(framePage) {
        engine.showPostsOn(framePage);
    });
});