首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步http请求的解耦设计

异步http请求的解耦设计
EN

Stack Overflow用户
提问于 2018-10-15 05:12:08
回答 1查看 232关注 0票数 0

我试图写的是一个视图->控制器->模型->客户端-> HttpRequestSender关系,这是抽象的,所以当我使用不同的平台(android,Fx-SpringRest)时,我可以替换HttpRequestSender。因为在android上,我需要使用一个非主线程来预置HttpRequest,所以我的解决方案是使用从控制器向下抛出链发送的回调来启用所需的异步行为。

我的问题是,尽管这是一个可行的解决方案,但是代码变得非常难以理解。

因此,像registerDevice(String name)这样的简单方法-如下所示:

代码语言:javascript
复制
public class DeviceRegModel {

    DeviceClient client;

    DeviceInfoMgr deviceInfoMgr;

    public void registerDevice(String name) throws DeviceNameTakenException {
        checkIfNameTaken(name);

        Device device = client.createDevice().getBody();

        device.setName(name);

        client.updateDevice(device);

        deviceInfoMgr.set(name);
    }

    private void checkIfNameTaken(String name) throws DeviceNameTakenException {
        for(Device dev : client.getAllDevices()) {
            if(dev.getName() == name) {
                throw new DeviceNameTakenException();
            }
        }
    }

变成了:

代码语言:javascript
复制
public class DeviceRegModel implements IModel {



DeviceClient client;

    DeviceInfoMgr deviceInfoMgr;


    public void registerDevice(String name, HttpCallback callback)   {
        ResponseCommand onOk = (res) -> checkIfNameTaken(name, res, callback);
        HttpFailCommands onFail = callback.getOnFailCmds();

        client.getAllDevices(HttpCallback.build(onOk, onFail));

    }

    private void checkIfNameTaken(String name, IResponse res, HttpCallback callback)  {
        for(Device dev : res.<Device[]>getBody()) {
            if(dev.getName() == name) {
                ExceptionCommand failCmd = callback.getOnFailCmds().getInternalFailCmd();
                failCmd.execute(new DeviceNameTakenException());
            }
        }
        createDevice(name,callback);
    }

    private void createDevice(String name, HttpCallback callback) {
        ResponseCommand onOk = (res) -> setNameLocally(name, res, callback);
        HttpFailCommands onFail = callback.getOnFailCmds();

        client.createDevice(HttpCallback.build(onOk, onFail));
    }

    private void setNameLocally(String name, IResponse res, HttpCallback callback) {
        Device device = res.<Device>getBody();
        device.setName(name);

        ResponseCommand onOk = (cmdRes) -> updateServer(name, cmdRes, callback);
        HttpFailCommands onFail = callback.getOnFailCmds();

        client.updateDevice(device, HttpCallback.build(onOk, onFail));
    }

    private void updateServer(String name, IResponse res, HttpCallback callback) {
        deviceInfoMgr.set(name);
        callback.getOnOkCmd().execute(res);
    }
}

我正在试图找出我在这里的正确路径(第二个版本),还是应该更改我的设计?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-17 03:34:20

当您想要编写可能涉及大量异步步骤的计算时,没有任何真正好的选项可以让您编写超级干净的代码。

在可用的选项中--事件驱动的设计、连续传递、monads等等-- monads是现代的选择,因为它们允许您编写与等效同步代码具有相同基本结构的异步代码。它仍然不是很漂亮的代码,但至少它是由相同的功能块构建的。

在JavaScript中,异步monad是有希望的,而在JavaScript/CompletableFuture中是有希望的。这就是您的类在这种风格中的样子(我假设对client的所有调用都是异步的,并返回一个CompletionStage):

代码语言:javascript
复制
DeviceClient client;

DeviceInfoMgr deviceInfoMgr;

public CompletionStage<Void> registerDevice(String name) {

    return checkIfNameTaken(name)
        .thenCompose( (unused) -> client.createDevice())
        .thenCompose(deviceResponse -> {
            Device device = deviceResponse.getBody();
            device.setName(name);
            return client.updateDevice(device);
        }).thenApply(unused -> {
            deviceInfoMgr.set(name);
            return (Void)null;
        });
}

private CompletionStage<Void> checkIfNameTaken(String name) {

    return client.getAllDevices()
        .thenCompose(devices -> {

            for(Device dev : devices) {
                if(dev.getName() == name) {
                    //I use a helper for this
                    CompletableFuture<Void> err = new CompletableFuture<>();
                    err.completeExceptionally(new DeviceNameTakenException());
                    return err;
                }
            }
            return CompletableFuture.completedFuture((Void)null);
        });
}

您可以看到,它具有与以前相同的方法,而这些方法所做的事情与以前的相同,并且它们使用相同的操作顺序来执行.但是现在它们返回一个CompletionStage,这表明它们可以异步运行,并且结果可能取决于那些方法返回时没有完成的事情。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52810074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档