1

たとえば、以下のコードを確認してみましょう

private void loadUserFromServer() {
    dispatchAsync.execute(new FindLoggedUserAction(),
          new AsyncCallback<FindLoggerUserResult>() {
        @Override
        public void onFailure(Throwable caught) {
             //do something
        }

        @Override
        public void onSuccess(BuscarUsuarioLogadoResult result) {
           //dosomething with user
           result.getUser();

       }
       operationTwo();
}

私の問題は、operationTwo();を実行する必要があることです。dipatcherの何らかの結果(成功または失敗)の後。

これは単なる例です。onSucessまたはonFailure()内にoperationTwo()を配置できないと仮定しましょう。

私の本当の問題

ユーザーがログインしている必要があるプレゼンターの私のGateKeeper。

private UserDTO user;
@Override
public boolean canReveal() {
        if(getUser() == null){
            ShowMsgEvent.fire(eventBus,"Must Login first", AlertType.ERROR);
            return false;
        }
        return true;
    }
}
public UserDTO getUser()
{
    if(user == null) 
    {
        //call server
        loadUserFromServer();
    }
    return user;
}
 private void loadUsuarioFromServer() {
    dispatchAsync.execute(new BuscarUsuarioLogadoAction()
     ,new AsyncCallback<BuscarUsuarioLogadoResult>() {
        @Override
        public void onFailure(Throwable caught) {
             //something
        }

        @Override
        public void onSuccess(BuscarUsuarioLogadoResult result) {
            if(!(result.getDto().equals(user)))
            {
                setUsuario(result.getDto(), false); //Set user UserDTO user
                //event for update Presenter Login/Logout
                // and Label with username
                fireUserUpdateEvents();
            }
            else
            {
                setUsuario(result.getDto(), false);
            }
        }
    });

ご覧のとおり、そのゲートキーパーを持つプレゼンターが呼び出され、ユーザーがnullの場合、getUser()が呼び出されますが、ディスパッチが実行されると、メソッドは成功または失敗が返されるまで待機しません。

結果:getUser()はnullを返します。

ディスパッチが成功した後、getUser()はDTOを返します。しかし、ご覧のとおり、canReveal()はすでにfalseを返しています。

4

3 に答える 3

3

あなたの場合、GateKeeper がセキュリティを処理するための良いアプローチだとは思わないでください。安定した仕事に就くことができなくなります。あなたが持つであろう問題:

  1. ネットワーク接続の切断を処理していません。コードが既にキャッシュされているが、ユーザーをリロードする必要がある場合、二重チェックで大きな問題が発生します。
  2. 特にネットワーク接続が悪い場合、同期呼び出しは常に問題になります。応答しないメッセージが大量に表示されます。

プレゼンター アクセスを処理するには、revealInParent メソッドを使用することをお勧めします。プレゼンターのほとんどはすでにそれをオーバーライドしており、次のようになっています。

@Override
protected void revealInParent() {
    RevealContentEvent.fire(...);
}

したがって、実際にユーザー データをダウンロードする前に Reveal イベントを発生させることはできません。あなたの場合、コードは次のようになります。

 @Override
 protected void revealInParent() {
   if(getUser() == null){
        RevealContentEvent.fire(...);
        return;
   }  
   dispatchAsync.execute(new BuscarUsuarioLogadoAction()
   ,new AsyncCallback<BuscarUsuarioLogadoResult>() {
      @Override
      public void onFailure(Throwable caught) {
           //something
      }

      @Override
      public void onSuccess(BuscarUsuarioLogadoResult result) {
        if(!(result.getDto().equals(user)))
        {
            setUsuario(result.getDto(), false); //Set user UserDTO user
            //event for update Presenter Login/Logout
            // and Label with username
            fireUserUpdateEvents();
        }
        else
        {
            setUsuario(result.getDto(), false);
        }
        RevealContentEvent.fire(...);
      }
   });
于 2012-12-07T21:38:55.320 に答える
1

はい、前の回答で Abhijith が述べたように、2 つのオプションがあります - 1) 同期呼び出し - GWT はサポートしていません。したがって、除外されます。2) タイマーの設定 - ユーザーがログインしない限り、コントロールはタイマー ループから抜け出せません。そのため、タイマーから失敗ステータスが返されることはありません。このアプローチは、要件の半分しか提供しません (成功状態のみを提供します)。

問題を解決するには、次のコード スニペットを試してください -

private UserDTO user;
private CanRevealCallBack revealCallBack; 

public interface CanRevealCallBack {
     returnStatus(boolean status);
}

@Override
public void canReveal(CanRevealCallBack callBack) {
    revealCallBack = callBack;
    if(user == null){
          loadUserFromServer();       
    }
    else{
          revealCallBack.returnStatus( true );
    }
}

private void loadUsuarioFromServer() {
dispatchAsync.execute(new BuscarUsuarioLogadoAction()
 ,new AsyncCallback<BuscarUsuarioLogadoResult>() {
    @Override
    public void onFailure(Throwable caught) {
         //something
    }

    @Override
    public void onSuccess(BuscarUsuarioLogadoResult result) {
        if(!(result.getDto().equals(user)))
        {
            setUsuario(result.getDto(), false); //Set user UserDTO user
            //event for update Presenter Login/Logout
            // and Label with username
            fireUserUpdateEvents();
        }
        else
        {
            setUsuario(result.getDto(), false);
        }

        if(result.getDto() == null){
            revealCallBack.returnStatus( true );  
        }
        else{
            revealCallBack.returnStatus( false ); 
        }
    }
});

したがって、revealCallback を canReveal メソッドに渡す必要があります。CallBack が実行され、非同期呼び出しの成功のステータスが返されます。コールバックの returnStatus メソッドでは、正しいユーザー ログイン ステータスを使用してロジックをプログラムできます。

于 2012-12-07T16:04:12.330 に答える
1

私たちも同様の問題に遭遇しました。非同期呼び出しチェーンを使用することをお勧めします。それができないので、問題には2つのオプションがあります

  1. ユーザーがnullかどうかを時々チェックし、ユーザーが入力された後にのみ戻るタイマーをセットアップします。
  2. JSNI (ネイティブ コード) を使用して、同期呼び出しを行います。しかし、これは悪い習慣であることに注意してください
于 2012-12-07T12:27:27.753 に答える