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 的一些结果之后(成功或失败)。

这只是一个示例,假设我不能将 operationTwo() 放入 onSucess 或 onFailure()

我真正的问题

该用户必须登录的演示者的我的 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);
            }
        }
    });

如您所见,当调用具有该 Gatekeeper 的 Presenter 并且用户为 null 时,会调用 getUser(),但是当 dispatch 执行时,该方法不会等到 Sucess 或 Failure 返回

结果:getUser() 返回 null。

在 dispatch 成功后,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

我们也遇到过类似的问题。最好使用异步调用链。由于您不能这样做,因此您的问题有两种选择

  1. 设置一个计时器,该计时器将不时检查用户是否为空,并且仅在填充用户后才返回。
  2. 使用 JSNI(本机代码)并进行同步调用。但要注意这是不好的做法
于 2012-12-07T12:27:27.753 回答
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 回答