【问题标题】:GWT : best way to do an initial RPC call at startup?GWT:在启动时进行初始 RPC 调用的最佳方式?
【发布时间】:2011-12-16 13:48:31
【问题描述】:

使用 GWT 在启动时执行初始 RPC 调用的最佳方式是什么?

我想检索在用户加载页面时在服务器端动态生成的配置数据。但是如果我从浏览器执行异步 RPC 调用来检索数据,有时在页面完全加载之前我没有得到响应,导致页面无法访问该配置数据。 (例如没有 Thread.sleep() 函数)

谢谢


感谢@Steve-J 的回复,我找到了解决方案...

基本思路如下:

  • 创建一个新的 StartupCompleted 事件
  • 在 onModuleLoad() 中启动初始 RPC 调用
  • 在该 RPC 调用的 onSucess 方法中,触发 StartupCompleted 事件
  • 在 App Controller 的 go() 方法的末尾,而不是在 History [ 中插入默认操作,并带有 History.newItem("default"); ],或者如果通过书签 [ 使用 History.fireCurrentHistoryState() 调用,则触发当前的历史状态; ],不要做任何事情
  • 在事件总线上为新的 StartupCompleted 事件注册一个处理程序
  • 当 StartupCompleted 事件被触发时,捕获它,然后在历史记录中插入默认操作或触发当前历史记录状态

等等……

初始 RPC 调用在执行任何其他操作之前完成......

这种方法有什么问题吗?

请注意,正如@Tom-Miette 所建议的那样,在收到 StartupCompleted 事件之前,最好有一个简单的“正在加载...”消息。

【问题讨论】:

    标签: gwt rpc


    【解决方案1】:

    您是否将消息传递用于控制流?我进行 RPC 调用,并在成功时发送消息,触发第一个活动弹出窗口供用户交互。失败时,会触发一条不同的消息,触发弹出窗口告诉用户他无法继续。

    不要忘记在弹出窗口上启用玻璃面板,这样用户在等待时就不会在后台弄乱任何东西。

    更新: 来自 cmets:“但我的问题是用户可以为页面添加书签,无需任何交互即可直接访问它。我可能最终导致我没有收到 RPC 调用的结果,但是我正在生成他请求的页面。即使在那一代我尝试检查我是否收到了结果,我也无法暂停直到完成页面生成之前的情况。”

    啊,我明白了。好的,GWT 有一个解决方案。你应该看看Activities and Places。当用户为“页面”添加书签时,他实际上是在为 GWT 应用程序的状态添加书签。当他返回到那个“页面”时,Activity 被触发并自动调用 start() 方法。这是您从服务器检索数据并进行任何其他所需设置的机会。获得数据后,您的 start() 方法将继续设置所谓的“视图”。从用户的角度来看,“页面”已经“加载”了。

    【讨论】:

    • 这个。让你的第一个模块入口点是 RPC 调度程序,回调创建你的 UI。
    • 是的,我愿意。但我的问题是用户可以为页面添加书签,无需任何交互即可直接访问。我可能会遇到这样的情况:我没有收到 RPC 调用的结果,但是我正在生成他请求的页面。即使在那一代我尝试检查我是否收到了结果,在完成页面生成之前我也不能暂停。
    • 无论你的 GWT 模块启动时的 url 是什么,都会首先执行入口点。能否在设置 UI 之前等待回调,并将这些数据存储在本地,以便在所有“页面”中访问。
    • 他如何为页面添加书签?您在使用活动和地点吗?当您为 Place 添加书签然后返回到它时,Activity Mapper 始终首先执行启动方法,您可以在该方法中调用服务器获取数据,然后根据这些结果呈现页面。根据您在此处所说的内容,我已经扩展了我的答案。
    • @Steve-J 实际上我正在使用“活动和地点”之前的消息和书签。 (使用 GWT 网站上记录的 History.newItem() 和 History.fireCurrentHistoryState() )不幸的是,在执行对应于书签 url 的 History.newItem() 之前,我找不到暂停流程的方法,在以防我的数据尚未加载。
    【解决方案2】:

    不确定这是否是最好的方法,但一个好的方法是完全避免初始调用,并使用 jsp 页面而不是 html 页面作为进入应用程序的入口点。然后,您可以在页面服务器端的 javascript 中为您的初始状态设置变量,例如

    <script type="text/javascript">
        var InitialState = {
        "userName" : "<%= userName %>",
        "emailAddress" : "<%= emailAddress %>",
        etc...
    };
    

    在您的 GWT 应用程序中,您可以使用 GWT Dictionary 类读取这些值

    Dictionary state = Dictionary.getDictionary("InitialState");
    String userName = state.get("userName");
    String emailAddress = state.get("emailAddress");
    

    【讨论】:

    • 也不确定这是否是最好的方法,但这听起来像是解决问题的一种方法。唯一关心的是以这种方式预加载的数据量,以及您必须一次预加载所有内容而不是只加载所需内容的事实。谢谢。会试试的。
    【解决方案3】:

    用一种“加载屏幕”覆盖您的 html 页面:

    <div 
    id="loading"
    style="
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      width: 100%;
      background: black;
      color: white;"
    >
      Loading...
    </div>
    

    并在 RPC 成功/失败时将其删除:

    RootPanel.get("loading").getElement().removeFromParent();
    

    【讨论】:

    • 这是一个有趣的方法......但是它只能阻止用户做任何事情,直到您收到初始 RPC 调用的结果。但是在我的情况下,用户可以为 url 添加书签,并且特定页面将“准备好”,而无需用户执行任何操作。所以我可能仍然会到达初始 RPC 尚未返回的地步,但我需要数据来完成页面准备。
    【解决方案4】:

    FWIW 我有一个解决方案,它涉及暂停 EntryPoint.onModuleLoad() 直到 RPC 返回。

    我正在使用 依赖注入GWTP Dispatch,这使引导过程变得复杂。我还希望结果是我的系统(客户端)中的单例实例

    结果是 GWT 本机(无命令模式)RPC 调用,成功后启动依赖注入。

    EntryPoint class sn-p:

    @Override
    public void onModuleLoad() {
        SessionInfoProvider.init(new Runnable() {
            @Override
            public void run() {
                // can now complete setup
                AppInjector injector = GWT.create(AppInjector.class);
                injector.bootstrap();
            }
        });
    }
    

    SessionInfoProvidersn-p:

    public class SessionInfoProvider implements Provider<SessionInfo> {
    private static SessionInfo.Bean sessionInfo;
    
    /**
     * Needs to be called before the module is used.
     */
    public static void init(final Runnable onCompletion) {
        GreetingServiceAsync s = GWT.create(GreetingService.class);
        s.loadSessionInfo(new AsyncCallback<SessionInfo.Bean>() {
            @Override
            public void onFailure(Throwable caught) {
                GWT.log("Failed to retrieve Session Info");
            }
    
            @Override
            public void onSuccess(SessionInfo.Bean result) {
                GWT.log("Successfully retrieved session info bean.  Username:" + result.getUserName());
                sessionInfo = result;
                onCompletion.run();
            }
        });
    }
    
    @Override
    public SessionInfo get() {
        if (sessionInfo == null) throw illegalState("Session Info not ready.");
        return sessionInfo;
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-06
      • 2014-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多