解耦GWT异步回调

Bo *_*hen 6 gwt state asynchronous coding-style

我有以下问题:我正在尝试使用GWT建模流程,其中我有几个视图与几个提交按钮.按下button1将创建服务器交互,如果一切正常,将加载下一个视图.我的问题是,我现在得到了非常讨厌的意大利面条代码(只是非常高级,以告诉你我的意思):

onClick {
    AsyncCallback {
       onSuccess {

           load new view with another clickhandler and an asynccallback

       }
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法创建某种抽象或什么?也许是国家模式?怎么样?非常感谢!

Chr*_*her 6

这实际上是一个非常好的问题 - 可能是一个没有确定答案的问题.这是一个适用于许多框架的问题,而不仅仅是GWT,所以我喜欢你的想法,用一些简化的代码来看待它.我会让它更长一点,以显示即使只有4个非常简单的回调看起来像:

嵌套回调

alice.call("a", new Callback() {

  @Override
  public void onSuccess() {
    bob.call("b", new Callback() {

      @Override
      public void onSuccess() {
        charlie.call("c", new Callback() {

          @Override
          public void onSuccess() {
            daisy.call("d", new Callback() {

              @Override
              public void onSuccess() {
                // finished
              }

            });
          }

        });
      }

    });
  }

});
Run Code Online (Sandbox Code Playgroud)

命名回调

您可以使用IDE轻松地将其重构为命名回调(提示:请从下到上阅读回调!):

final Callback daisyCallback = new Callback() {

  @Override
  public void onSuccess() {
    // finished
  }
};

final Callback charlieCallback = new Callback() {

  @Override
  public void onSuccess() {
    daisy.call("d", daisyCallback);
  }
};

final Callback bobCallback = new Callback() {

  @Override
  public void onSuccess() {
    charlie.call("c", charlieCallback);
  }
};

final Callback aliceCallback = new Callback() {

  @Override
  public void onSuccess() {
    bob.call("b", bobCallback);
  }
};

alice.call("a", aliceCallback);
Run Code Online (Sandbox Code Playgroud)
  • 问题:控制流程不再那么明显了.
  • 仍然,IDE可以通过使用"搜索引用"(Eclipse中的Ctrl-G)或类似的东西来提供帮助.

事件总线(或观察者/发布 - 订阅模式)

这是与事件总线相同的调用方式:

alice.call("a", new Callback() {

  @Override
  public void onSuccess() {
    bus.fireEvent(BusEvent.ALICE_SUCCESSFUL_EVENT);
  }
});

bus.addEventListener(BusEvent.ALICE_SUCCESSFUL_EVENT, new BusEventListener() {

  @Override
  public void onEvent(final BusEvent busEvent) {
    bob.call("b", new Callback() {

      @Override
      public void onSuccess() {
        bus.fireEvent(BusEvent.BOB_SUCCESSFUL_EVENT);
      }
    });

  }
});

bus.addEventListener(BusEvent.BOB_SUCCESSFUL_EVENT, new BusEventListener() {

  @Override
  public void onEvent(final BusEvent busEvent) {
    charlie.call("c", new Callback() {

      @Override
      public void onSuccess() {
        bus.fireEvent(BusEvent.CHARLIE_SUCCESSFUL_EVENT);
      }
    });

  }
});

bus.addEventListener(BusEvent.CHARLIE_SUCCESSFUL_EVENT, new BusEventListener() {

  @Override
  public void onEvent(final BusEvent busEvent) {
    daisy.call("d", new Callback() {

      @Override
      public void onSuccess() {
        bus.fireEvent(BusEvent.DAISY_SUCCESSFUL_EVENT);
      }
    });

  }
});

bus.addEventListener(BusEvent.DAISY_SUCCESSFUL_EVENT, new BusEventListener() {

  @Override
  public void onEvent(final BusEvent busEvent) {
    // finished
  }
});
Run Code Online (Sandbox Code Playgroud)
  • 在适当的情况下(非常清楚每个事件的含义,如果你没有太多),这种模式可以使事情变得非常好和清晰.
  • 但在其他情况下,它可以使控制流程更加混乱(并且您可以轻松获得两倍的代码行).
  • 使用IDE来查找控制流程更加困难.
  • GWT历史机制是一个非常积极的例子,可以合理地使用这种技术.

分而治之

根据我的经验,通过混合嵌套和命名回调来"划分和征服"通常是一个好主意:

final Callback charlieCallback = new Callback() {

  @Override
  public void onSuccess() {

    daisy.call("d", new Callback() {

      @Override
      public void onSuccess() {
        // finished
      }
    });
  }
};

alice.call("a", new Callback() {

  @Override
  public void onSuccess() {

    bob.call("b", new Callback() {

      @Override
      public void onSuccess() {

        charlie.call("c", charlieCallback);
      }
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

根据具体情况,两个嵌套回调通常仍然可读,并且当读取代码50%时,它们会减少方法之间的跳跃.

(我在这里创建了一个我的示例的pastebin,如果你喜欢玩它们:http://pastebin.com/yNc9Cqtb)


kri*_*arp 0

避免小部件之间耦合的建议方法是使用 EventBus。在此处阅读更多详细信息https://developers.google.com/web-toolkit/articles/mvp-architecture#events

希望能帮助到你。