【问题标题】:Pattern for cascade/nested asynchronous calls级联/嵌套异步调用的模式
【发布时间】:2012-10-13 16:38:25
【问题描述】:

在客户端使用 gwt 时,通常会调用异步方法并在回调方法中进行处理。

asyncService.method(new AbstractAsyncCallback<Number>() {
  @Override
  public void onSuccess(Number num) {
    // do something with number
  }
});

但经常遇到需要从一个异步方法获取结果、传递给另一个方法等情况。这就是为什么我们会得到脏的级联代码,很难阅读。

asyncService.method(new AbstractAsyncCallback<Number>() {
      @Override
      public void onSuccess(Number num) {
        asyncService.method1(num, new AbstractAsyncCallback<String>() {
          @Override
          public void onSuccess(String str) {
             asyncService.method2(str, new AbstractAsyncCallback<Void>() {
               @Override
               public void onSuccess(Void void) {
                 // do something
               }
             });
          }
        });
      }
    });

我知道,我们可以将服务器端的这三个调用组合成单独的服务方法,但是如果我们需要很多这样的不同方法的组合呢?另一个问题是添加单独的方法,它执行我们可以通过简单组合现有方法获得的功能。

是否有一个通用的模式可以摆脱此类代码而不更改服务器端服务?

【问题讨论】:

  • 恕我直言,您的问题还应包括 onFailure 方法
  • @Jean-MichelGarcia onFailure 为简单起见省略。顺便说一句,AbstractAsyncCallback 有它的默认实现。

标签: java design-patterns gwt asynchronous


【解决方案1】:

您概述了一种模式:一系列调用。仅当第二次调用取决于第一次调用的结果等时才应使用此模式。

如果您可以并行执行请求,那么您应该这样做。一种选择是在继续之前等待其他方法完成的目标方法。在这个例子中 showPerson() 会被调用两次,但是当所有数据都准备好时它只会执行一次。

Integer age = null;
String name = null;

asyncService.method(new AbstractAsyncCallback<Integer>() {
    @Override
    public void onSuccess(Integer num) {
        age = num;
        showPerson();
    }
});
asyncService.method(new AbstractAsyncCallback<String>() {
    @Override
    public void onSuccess(String n) {
        name = n;
        showPerson();
    }
});

private void showPerson() {
    if (name != null && age != null) {
        myView.showPerson(name, age);
    }
}

【讨论】:

【解决方案2】:

您可以创建命名类,而不是使用匿名类。这将消除令人困惑的嵌套,如果您使用有意义的名称,可能会使您的代码更易于理解。

【讨论】:

  • @Eduardo 如果我们创建命名函数,我们的可读性会略有提高,但我们会创建很多一次性名称,填充我们的命名空间,实际上没有任何理由。我们还需要以一种向后的方式创建这样的嵌套函数:从最内层到最顶层,不遵循调用逻辑
  • @mishadoff:我明白。当我在 ActionScript 中编程时,我遭受了同样的痛苦。它稍微清理了一些混乱,但会产生其他问题。
【解决方案3】:

我们通常更喜欢使用匿名回调实现来定义变量,这些变量在代码中处于同一级别,因此它们更具可读性,并且我们倾向于对它们进行排序以理解工作流程。另一个目标是这些回调可以重复使用。

  AsyncService asyncService = GWT.create(AsyncService.class);

  AsyncCallback<Number> onMethod1Response = new AbstractAsyncCallback<Number>() {
    public void onSuccess(Number num) {
      asyncService.method2(onMethod2Response);
    }
  };

  AsyncCallback<String> onMethod2Response = new AbstractAsyncCallback<String>() {
    public void onSuccess(String str) {
      // do something
    }
  };  

  asyncService.method1(onMethod1Response);

【讨论】:

  • 好点,新的回调会导致 IE 中的内存泄漏,因此仅使用它们的一个实例并重用它们可以避免旧浏览器中的问题。我为此 +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-15
相关资源
最近更新 更多