首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将异步HTTP请求抽象为同步

如何将异步HTTP请求抽象为同步
EN

Stack Overflow用户
提问于 2018-07-05 16:11:20
回答 1查看 940关注 0票数 3

我有一个第三方REST服务,它的行为是“异步的”;就像在请求中使用中间响应进行响应一样,中间响应由与中间响应相关的回调补充。

回调几乎立即通过“回调URL”返回。

我试图设计一种解决方案,某种程度上是一种适配器来调用这个资源,就好像它是“同步的”,因为处理回调非常麻烦,特别是当我需要通过同一个第三方顺序处理其他类似API的连续请求时。基本上,我希望抽象绿色部分,以便调用方只获得完全回调、错误或超时异常。

我的研究重点是使用RxJava,但我不知道如何用反应性编程的原则来解决这个问题(我的理解是有限的)。

设计考虑因素:

  1. 将相关器持久化到数据存储以供以后在回调时查找是不可取的,因为它很昂贵。
  2. 回调的等待策略是可以的,因为回调的响应时间小于1秒。

如何使用CompletableFutureObservable-Observer模式等待回调并返回给调用方?

EN

回答 1

Stack Overflow用户

发布于 2018-07-05 18:52:10

考虑使用CountDownLatch对主线程进行等待,直到工作线程处理了第三方API。工作人员获得回调,以便知道请求何时已取得进展、是否完成、超时、是否有错误等。

下面是一个粗略的模拟:

代码语言:javascript
复制
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;

public class TreatAsSync {

    public static void main(String[] args) {
        TreatAsSync app = new TreatAsSync();
        app.call();
    }

    private void call() {
        RestClient restClient = new RestClient();
        Request request = new Request();
        Response response = restClient.call(request);
        System.out.println("Response was: " + response);
    }

    private class Request {

    }

    private class Response {
        private final boolean error;
        private final boolean timedOut;
        private final String result;

        public Response(boolean error, boolean timedOut, String result) {
            this.error = error;
            this.timedOut = timedOut;
            this.result = result;
        }

        public String toString() {
            return "error:" + error + ", timedOut: " + timedOut + ", result: " + result;
        }
    }

    private class ResponseWrapper {
        private Response response;

        public Response getResponse() {
            return response;
        }

        public void setRespose(Response response) {
            this.response = response;
        }
    }

    private class RestClient {

        public Response call(Request request) {
            ResponseWrapper wrapper = new ResponseWrapper();
            CountDownLatch latch = new CountDownLatch(1);

            ThirdPartyRunner runner = new ThirdPartyRunner(request, wrapper, latch);
            new Thread(runner).start();

            try {
                latch.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            return wrapper.getResponse();
        }
    }

    private interface ThirdPartyCallBack {
        public void onProgress(Response response);
        public void onComplete(Response response);
        public void onTimeOut(Response response);
        public void onError(Response response);
    }

    private class ThirdPartyRunner implements ThirdPartyCallBack, Runnable {
        private final Request request;
        private final ResponseWrapper wrapper;
        private final CountDownLatch latch;

        public ThirdPartyRunner(Request request, ResponseWrapper wrapper, CountDownLatch latch) {
            this.request = request;
            this.wrapper = wrapper;
            this.latch = latch;
        }

        @Override
        public void onProgress(Response response) {
            System.out.println("some progress was made...");
        }

        @Override
        public void onComplete(Response response) {
            System.out.println("request completed");
            finished(response);
        }

        @Override
        public void onTimeOut(Response response) {
            System.out.println("request timed out");
            finished(response);
        }

        @Override
        public void onError(Response response) {
            System.out.println("request had an error");
            finished(response);
        }

        private void finished(Response response) {
            wrapper.setRespose(response);
            latch.countDown();
        }

        @Override
        public void run() {
            try {
                callThirdParty();
            } catch (Exception e) {
                finished(new Response(true, false, e.getMessage()));
            }
        }

        private void callThirdParty() {
            // simulate api.call(request, this);
            for (int i = 0; i < ThreadLocalRandom.current().nextInt(10) + 1; i++) {
                onProgress(new Response(false, false, "in progress"));
            }

            switch (ThreadLocalRandom.current().nextInt(3)) {
            case 0:
                onComplete(new Response(false, false, "done"));
                break;

            case 1:
                onTimeOut(new Response(false, true, "hello?"));
                break;

            case 2:
                onError(new Response(true, false, "uh oh!"));
                break;
            }
        }
    }

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

https://stackoverflow.com/questions/51195868

复制
相关文章

相似问题

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