同步异步回调方法调用

huangapple go评论75阅读模式
英文:

Synchronize the asynchronous callback method call

问题

我们正在开发一个类似这样的解决方案;

请求:(我们通过 API 调用接收请求,并通过我们使用的库发送到第三方)
我们的客户端 --> 我们的 API --> 第三方

响应:(这个响应是我们通过我们正在使用的库中提供的回调方法异步从第三方接收的)
第三方 --> 我们的代码 --> 我们的客户端

以下是相关代码,并且希望摆脱 Thread.sleep() 的调用,改用回调来提供响应。

----- API 方法 -------------

    @GetMapping
    	public ResponseEntity<String> getData(@RequestBody String requestId) throws SessionNotFound, InterruptedException {
    		dataService.get(requestId);
    		String msg;
    		long start = System.currentTimeMillis();
    		do {
                // 我们希望摆脱这个 sleep() 语句,并以某种方式在此处进行回调,一旦有消息就立即回调。
    			Thread.sleep(30);
    			msg = clientApp.getRespnse(requestId);
    		} while(msg == null);
    		return ResponseEntity.ok(msg);
    	}


------- Service 类和方法 ---------------

@Service
public class DataService {
	
	
	@Autowired
	private ClientApp clientApp;
	
	public void get(String requestId) throws SessionNotFound {
// 这个方法来自我们使用的库。它只提交请求,响应在不同的方法中接收。
        send(requestId);        
	}


------- Component 类和方法 ---------------

@Component
public class ClientFixApp {

    private Map<String, String> responseMap = new HashMap<>();

// 这个方法是来自第三方库的回调,每当有响应时,这个方法将被调用,我们需要将这个消息作为 API 调用的响应发送出去。
    @Override
	public void onResponse(String requestId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
		responseMap.put(msgId, jsonMsg);
	}

  public String getRespnse(String requestId) {
		return responseMap.get(requestId);
	}
}
英文:

We are working on a solution which is like this;

Request: (We receive the request via API call and send to third-party via a library we use)
OUR-Client --> OUR-API --> THIRD-PARTY

Response: (This response we receive from third-party asynchronously through a callback method given in the library we are using)
THIRD-PARTY --> OUR-CODE --> OUR-Client

Here is the below code and want to get rid of Thread.sleep() call and make use of the callback to provide response.

----- API Method -------------

    @GetMapping
    	public ResponseEntity<String> getData(@RequestBody String requestId) throws SessionNotFound, InterruptedException {
    		dataService.get(requestId);
    		String msg;
    		long start = System.currentTimeMillis();
    		do {
                // We want to get rid of this sleep() statement and some way to callback here as soon there is message.
    			Thread.sleep(30);
    			msg = clientApp.getRespnse(requestId);
    		} while(msg == null);
    		return ResponseEntity.ok(msg);
    	}


------- Service Class and Methods ---------------

@Service
public class DataService {
	
	
	@Autowired
	private ClientApp clientApp;
	
	public void get(String requestId) throws SessionNotFound {
// This method is from the library we use. This only submits the request, response is received on different method.
        send(requestId);        
	}


------- Component Class and Methods ---------------

@Component
public class ClientFixApp {

    private Map<String, String> responseMap = new HashMap<>();

// This method is callback from the third party library, whenever there is response this method will get invoked and this message we need to send as response of the API call.
    @Override
	public void onResponse(String requestId)
			throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
		responseMap.put(msgId, jsonMsg);
	}

  public String getRespnse(String requestId) {
		return responseMap.get(requestId);
	}
}

答案1

得分: 1

DataServiceClientFixApp的设计存在缺陷(事实上,它们是两个不同的类,而应该只有一个,这已经说明了很多问题)。真正的异步程序必须允许注册用户过程作为回调,在I/O操作完成时调用(无论是成功还是失败)。ClientFixApp在不引起客户端其他选项(除了轮询)的情况下,悄然将结果写入表中。

英文:

DataService and ClientFixApp are flawed by design (the very fact it is 2 different classes while there must be one, speaks a lot). Truly asynchronous programs must allow to register user procedure as a callack, called when the I/O operation finished (successfully or not). ClientFixApp silently writes the result in a table, leaving for client no other option except polling.

答案2

得分: 0

你可以使用任何现有的异步 HTTP 库。例如,下面是在 Java 11 及更高版本中包含的 java.net.http 库的代码示例。其他库具有类似的功能。

public static CompletableFuture<HttpResponse<String>> doGet(String uri) {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(uri))
            .build();
    return client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
}

public static void main(String[] args) {
    CompletableFuture<HttpResponse<String>> future = doGet("https://postman-echo.com/get");
    future.thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();
}
英文:

You can use any existing asynchronous http library. For example, below is the code for the library java.net.http included in Java 11 and later. Other libraries have similar functionality.

public static CompletableFuture&lt;HttpResponse&lt;String&gt;&gt; doGet(String uri) {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(uri))
            .build();
    return client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
}

public static void main(String[] args) {
    CompletableFuture&lt;HttpResponse&lt;String&gt;&gt; future = doGet(&quot;https://postman-echo.com/get&quot;);
    future.thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();
}

huangapple
  • 本文由 发表于 2020年10月9日 18:58:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/64278679.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定