【问题标题】:Bestpractice for multiple GWT-RPC calls多个 GWT-RPC 调用的最佳实践
【发布时间】:2013-03-22 19:05:29
【问题描述】:

我必须进行几次 GWT-RPC 调用。 我想像这样异步启动它们。

service.s1(param1, callback1);
service.s2(param2, callback2);
service.s3(param3, callback3);

我不确定如何“同步”这三个回调。 下一个动作,例如调用方法 nextMethod();应在三个回调完成后完成。 是否有“最佳实践”如何做到这一点?

我想建立一个像这样的小服务类

public class ServiceSync
{ private boolean[] callReady;

  public ServiceSync(int n)
  { callReady = new boolean[n];
    for(int i=0; i<n;i++)
    {  callReady[i]=false;
    }
  }

  public boolean setReady(int i)
  { callReady[i]=true;
    for(boolean b : callReady)
    { if (!b) return false;    
    }
    return true;
  }
}

在回调中我会说

if (serviceSync.setReady(myId))
{ nextMethod();}

但我不确定这是不是个好主意。 特别是我不确定是否会出现问题,如果 2 个回调“同时”调用此服务类

【问题讨论】:

  • 要不要一个接一个地调用一个方法,我的意思是第二个调用依赖于第一个调用返回的数据吗?
  • 不,调用应该是“并行的”,我认为代码就是这样做的。这是真的吗?
  • 所以你想在所有三个调用都成功的情况下执行一个方法,但是你并行发送调用,对吗?如果是这样,你的代码不清楚你所说的,你在callback1、callback2和callback3中有什么代码?
  • 回调存储接收到的数据。
  • 好的,发布我的回复

标签: gwt gwt-rpc


【解决方案1】:

看来这是典型案例,Promises可以解决。

遵循 DRY 的原则,我不会自己编写代码,而是使用为 gwt 编写的gwtquery Promises 解决方案,基于流行的 jQuery Deferred 实现。

在您的情况下,您的代码可能如下所示:

    // Create 3 promises to be used in RPC
    PromiseRPC<String> promise1 = new PromiseRPC<String>();
    PromiseRPC<String> promise2 = new PromiseRPC<String>();
    PromiseRPC<String> promise3 = new PromiseRPC<String>();

    // Fire the asynchronous requests
    greetingService.greetServer(textToServer1, promise1);
    greetingService.greetServer(textToServer2, promise2);
    greetingService.greetServer(textToServer3, promise3);

    GQuery
          // 'when' returns a new promise which monitors all of its subordinates
          .when(promise1, promise2, promise3)
          // 'done' will be executed only in the case all promises succeed
          .done(new Function() {
            public void f() {
              // each promise store its result in a fixed position of the argument list
              String textFromServer1 = arguments(0, 0);
              String textFromServer2 = arguments(1, 0);
              String textFromServer3 = arguments(2, 0);
            }
          });

    // If you want you could fire requests here instead than above

【讨论】:

  • 非常聪明的解决方案,我几天前才发现 gquery,它似乎是使用 GWT 开发时必不可少的工具
  • @Manolo,你能帮帮我吗?我尝试了这种方法,但似乎万一任何一个服务调用失败 - 除了失败服务的异常,我们无法得到任何结果。
  • 您必须使用fail 方法然后查看发生了什么: GQuery.when(...).done(...).fail(new Function(){public void f( ){console.log(dumpArguments())}});
【解决方案2】:

为您的回调声明一个带有状态的接收器,例如:

public class CallResultReceiver {

   boolean call1Done, call2Done, call3Done;

   public void onCall1Success() { 
      call1Done = true;
      if (call1Done && call2Done && call3Done) { doGreatThings(); }
   }

   public void onCall2Success() { 
      call2Done = true;
      if (call1Done && call2Done && call3Done) { doGreatThings(); }
   }

   public void onCall3Success() { 
      call3Done = true;
      if (call1Done && call2Done && call3Done) { doGreatThings(); }
   }
}

【讨论】:

  • 也许它在功能上并没有太大的不同,但它更干净,更容易阅读 imo。
【解决方案3】:

他是Parallel asynchronous calls in GWT上最好的文章

通过编写一个简单的 ParentCallBack,您可以让您的事情变得简单高效。

public void someGwtClientSideMethod() {   
  SomeServiceAsync someService = GWT.create(SomeService.class);  
  ParallelCallback fooCallback = new ParallelCallback();  
  ParallelCallback barCallback = new ParallelCallback();  
  ParentCallback parent = new ParentCallback(fooCallback, barCallback) {   
    public void handleSuccess() {  
      doSomething(getCallbackData(0), getCallbackData(1));  
    }  
  };  
  someService.foo(fooCallback);  
  someService.bar(barCallback);  
} 

这里是Code for Parent Callback

【讨论】:

    【解决方案4】:

    这是我提出问题的方法:

    首先,我们需要在并行异步问题中使用某种 SynchronizedCounter:

    public class SynchronizedCounter {
    
        private int c = 0;
    
        public synchronized void increment() {
            c++;
        }
    
        public synchronized void decrement() {
            c--;
        }
    
        public synchronized int value() {
            return c;
        }
    }
    

    下一步是调用 RPC 方法,例如:

    private void fetchData() {
        getFirst();
        getSecond();
        getThird();
        getFourth();
    }
    

    每个 RPC 方法都必须在请求之前增加我们的计数器,并在调用成功后立即减少它。每个 RPC 方法都会在 RPC 调用之后调用 final 方法,该方法会检查请求的计数,例如:

    private void dataFetched() {
        if (counter.value() <= 0)
            // proceed
    }
    

    IMO 非常清晰和优雅的方法。希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2013-07-17
      • 2019-03-23
      • 2018-04-28
      • 1970-01-01
      • 2016-03-27
      • 2011-04-12
      • 2019-04-25
      • 2011-11-29
      • 1970-01-01
      相关资源
      最近更新 更多