等待应用程序返回成功或失败(AsyncCallBack)

时间:2012-12-07 10:20:19

标签: gwt asynchronous gwtp

例如,让我们检查下面的代码

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(),但是当调度执行时,该方法不会等到返回Sucess或Failure

结果:getUser()返回null。

在调度的成功结果之后,getUser()返回一个DTO。但是,正如你所看到的,canReveal()已经返回false。

3 个答案:

答案 0 :(得分:3)

不要认为GateKeeper是处理您案件安全性的好方法。你将无法达到稳定的工作。你会遇到的问题:

  1. 您没有处理丢失的网络连接。如果您的代码已经缓存但是您需要重新加载用户,那么双重检查将是一个很大的问题。
  2. 同步通话始终存在问题,特别是网络连接不良。你将收到大量没有回复的消息。
  3. 要处理演示者访问权限,最好使用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(...);
          }
       });
    

答案 1 :(得分:1)

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

  1. 设置一个计时器,该计时器将不时检查用户是否为空,并且仅在用户填充后返回。
  2. 使用JSNI(本机代码)并进行同步调用。但要注意这是不好的做法

答案 2 :(得分:1)

是的,正如Abhijith在之前的回答中提到的那样,有两种选择 - 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方法中,您可以使用正确的用户登录状态对逻辑进行编程。