3

次のプロパティを持つ JavaScript でコンストラクターを作成しています。

function WhizBang() {

   var promise;

   this.publicMethod_One = function publicMethod_One() { ... };
   this.publicMethod_Two = function publicMethod_Two() { ... };

   promise = asyncInit();
}

したがって、呼び出すとプロセスnew WhizBang()が開始されasyncInit()ます。上記のコードから明らかでないことは、この呼び出しが終了するまで、インターフェース内のパブリック メソッドはどれも実行されるべきではないということasyncInit()です。

したがって、 の定義は次のpublicMethod_One()ようになります。

function publicMethod_One() {

  promise
    .then( doStuff )
    .catch( reportInitFailure )
  ;

  function doStuff() { ... }
  function reportInitFailure() { ... }
}

で発生することのいくつかdoStuff()は非同期です。それらのいくつかはそうではありません。

したがって、私のクラスのエンドユーザーが次のようなことをしたとします。

function main() {

  var whizBang = new WhizBang();

  whizBang
    .publicMethod_One()
    .publicMethod_Two()
  ;
}

への呼び出しは、 が終了publicMethod_One()するまで行ってはなりませんasyncInit()。また、 と のpublicMethod_Two()両方が閉じられるまで呼び出しを行ってはasyncInit()なりませんpublicMethod_One()

クラスメソッドを連鎖可能に定義するにはどうすればよいですか?

私がする必要があると思うのは、パブリック メソッドがすべてthen()promise の呼び出しと同等であり、その後にクラス固有の実装要素が続くクラスを定義することです。

インターネット、ハーフ!

(回答でBluebird Promise Libraryを使用するとボーナス ポイントが得られます。)

4

1 に答える 1

4

あなたが今持っているもの

あなたが今持っているものは実際にはかなりいいです。promiseの結果をキャッシュしていてasyncInit、誰もが同じ promise を待っているため、promise が終了する前にこれらの関数のコードを実行することは不可能です。

function publicMethod_One() {    
  promise // the fact you're starting with `promise.` means it'll wait
    .then( doStuff )
    .catch( reportInitFailure );
}

そのため、使用するために人々を待たせるのではなく、publicMethod_Oneすぐに呼び出すことがdoStuffでき、promise のみを実行するなどのメソッドは解決されました。

流体インターフェース

コードに重大な問題があることに気付いたように、特定のメソッドがいつ実行するか、またはメソッドをシーケンスする方法を知る方法はありません。これは 2 つの方法で解決できます。

  • thisアクションごとに戻り、プロミスをキューに入れる流動的なインターフェースを作成します。
  • 各非同期呼び出しから promise を返します。

2 つのアプローチを見てみましょう。

流体インターフェース

これは、すべてのメソッドがインスタンスを返すことを意味します。また、「一度に」発生しないようにキューに入れる必要があります。promiseこれは、呼び出しごとに次のように変更することで実現できます。

function publicMethod_One() {    
  promise = promise // note we're changing it
    .then( doStuff )
    .catch( reportInitFailure );
  return this; // and returning `this`
}

また、現在の promise を返すメソッドを公開し.readyて、一連の操作を外部から待機できるようにすることもできます。

function ready(){
    return this.promise;
}

これにより、次のようなことが可能になります。

var ready = new WhizBang().publicMethod_One().publicMethod_One().ready();
ready.then(function(){
     // whizbang finished all operations
}); // can also add error handler

戻り値

私の意見では、これはより単純なアプローチです。すべてのメソッドは、作成した promise を返すため、個別に待機できます。

function publicMethod_One() {    
  return promise // note we're returning and not changing it
    .then( doStuff )
    .catch( reportInitFailure );
}

非同期操作が外部に公開されるため、これは便利です。

ブルーバードを次.bindのように使用しているため、チェーンが可能です。

var whiz = new WhizBang();
var res = Promise.bind(whiz).then(whiz.publicMethod_one)
                            .then(whiz.publicMethod_one);
res.then(function(){
     // all actions completed, can also use return values easier.
});

しかし、利点は、外部から推論する方が簡単であることです。このため、私はこのアプローチを個人的に好みます。個人的にはreturn、内部状態を変更するよりも意味のあるデータを常に好みます。

于 2015-02-06T23:02:11.477 に答える