【问题标题】:Understanding Playframework Promises - Client to Server request spawning multiple requests了解 Playframework Promises - 客户端到服务器请求产生多个请求
【发布时间】:2014-03-27 22:00:41
【问题描述】:

使用 Promises 试用 play 框架。

目标是向用户公开 API 本地主机:9000/状态

此调用应发送到MyServer/v1/agents 并以 Json 形式检索帐户列表。

["alpha", "beta"]

对于这些帐户中的每一个,都有另一个 api MyServer/v1/agents/<name>/status 将响应给定帐户的状态。

{"resultCode": 0, "resultDescription": "up"}

我想呈现给用户的最终结果应该是这样的:

{ "alpha": "false", "beta": "true" }

这是我尝试过的代码,但我得到了一个空的 Json 结果显示。 当我插入调试消息时,我最终会看到我的帐户填写了地图。

在游戏中做这样的事情的正确方法是什么?我应该使用 Actors 吗?

//This function sends out the request to get back the status for a given account  
 public static Promise<Boolean> isCampaignActive(String name) {
    Logger.debug("isCampaignActive:" + name);
    Promise<WS.Response> status = WS.url("http://MyServer/v1/agents/"+name+"/status").get();
    Promise<JsonNode> jsonResponse = status.map(Functions.responseToJson);
    Promise<Boolean> s = jsonResponse.map(new Function<JsonNode, Boolean>() {
       @Override
       public Boolean apply(JsonNode jsNode) {
           boolean asBoolean = jsNode.get("resultCode").asBoolean();
           return asBoolean;
       }
    });
    return s;
}



//This function is the API exposed to the client that should return the final result
public static Promise<Result> status() {
    Promise<WS.Response> accounts = WS.url("http://MyServer/v1/agents").get();
    Promise<JsonNode> responseJson = accounts.map(Functions.responseToJson);

    Promise<List<String>> accountList = responseJson.map(new F.Function<JsonNode, List<String>>() {

        @Override
        public List<String> apply(JsonNode jsonAccounts) throws Throwable {

            List<String> accountList = new ArrayList<String>();
            for(JsonNode accountName : jsonAccounts) {

                accountList.add(accountName.asText());
            }
            return accountList;
        }

    });

    Promise<Result> result = accountList.map(new F.Function<List<String>, Result>() {
        @Override
        public Result apply(List<String> list) throws Throwable {
            final Map<String, Boolean> tempMap = new HashMap<String, Boolean>();

            for (final String accountNamex : list) {
                Promise<Boolean> campaignActive = isCampaignActive(accountNamex);
                campaignActive.map(new F.Function<Boolean, Void>(){

                    @Override
                    public Void apply(Boolean status) throws Throwable {
                        tempMap.put(accountNamex, status);
                        return null;
                    }

                }
                );
            }


            Logger.debug(tempMap.toString());
            return ok(Json.toJson(tempMap));
        }});
    return result;

}

【问题讨论】:

    标签: playframework playframework-2.0


    【解决方案1】:

    我认为您代码中的问题主要是最后一次操作。

    在 map 中运行的函数的副作用不是线程安全的,因为它们可能在任何给定时刻返回,并且您不想同步,因为这会阻塞服务器的线程。所以你绝不能做你用tempMap做的事情。

    promise/futures 的想法是转换值,直到达到 Promise。而且由于这些操作不会触及每个 Function&lt;A, B&gt; 之外的任何可变状态,因此它是线程安全的并且可以并发运行。

    要从 List&lt;Promise&lt;Boolean&gt;&gt; 转到 Promise&lt;List&lt;Boolean&gt;&gt;,请查看 Promise.sequence:http://www.playframework.com/documentation/2.2.0/api/java/play/libs/F.Promise.html

    然后,您可以将 Promise&lt;List&lt;Boolean&gt;&gt; 转换为包含这些布尔值的 json 表示形式的 Promise&lt;Result&gt;

    【讨论】:

    • 谢谢,我会调查的。
    • 仍然不能完全修改它来工作。我是否试图以不正确的方式使用它,这不是典型的场景吗?
    • 您要解决的问题非常适合期货,您只需弄清楚通过一组函数传递不可变状态的想法,这些函数将按照您执行的顺序在线程上运行不知道。也许 Yevgeniy Brikman 的这篇文章可能会有所帮助:engineering.linkedin.com/34/play-framework-and-async-io
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多