From 86634625bdd0cd59fea6679e092064865ddc3e23 Mon Sep 17 00:00:00 2001 From: Georgi Grigorov <72125420+Grigorov-Georgi@users.noreply.github.com> Date: Thu, 15 Aug 2024 11:17:27 +0300 Subject: [PATCH] added async http request and removed old sync impl (#6) # Description In order to make http requests non-blocking the previous synchronous calls are replaced with asynchronous ones. Additionally, the new implementation in the http.js script utilizes async-await syntax, which is easier to understand than the old XMLHttpRequest approach. What does this PR do? Fixes https://github.com/LimeChain/Fruzhin/issues/506 How were these changes implemented and what do they affect? Changes have been made to the HttpRequest class and http.js script, which are called by the JsonUtil class. These modifications will not be visible to all users of the JsonUtil class. --------- Co-authored-by: Georgi Grigorov <georgi.grigorov@limechain.tech> --- .../java/com/limechain/teavm/HttpRequest.java | 32 ++++++++++++++++-- .../com/limechain/utils/json/JsonUtil.java | 5 ++- src/main/webapp/js/http.js | 33 +++++++++++-------- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/limechain/teavm/HttpRequest.java b/src/main/java/com/limechain/teavm/HttpRequest.java index 73684788e..a8c51b2b0 100644 --- a/src/main/java/com/limechain/teavm/HttpRequest.java +++ b/src/main/java/com/limechain/teavm/HttpRequest.java @@ -1,8 +1,36 @@ package com.limechain.teavm; +import lombok.extern.java.Log; +import org.teavm.interop.Async; +import org.teavm.interop.AsyncCallback; import org.teavm.jso.JSBody; +import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSObject; +import org.teavm.jso.core.JSError; +import java.util.logging.Level; + +@Log public class HttpRequest { - @JSBody(params = {"method", "url", "body"}, script = "return httpRequestSync(method, url, body);") - public static native String httpRequestSync(String method, String url, String body); + + @Async + public static native String asyncHttpRequest(String method, String url, String body); + + private static void asyncHttpRequest(String method, String url, String body, AsyncCallback<String> callback) { + createAsyncHttpRequest(method, url, body, (error, response) -> { + if (error != null) { + log.log(Level.WARNING, error.getMessage()); + } else { + callback.complete(response); + } + }); + } + + @JSBody(params = {"method", "url", "body", "callback"}, script = "return asyncHttpRequest(method, url, body, callback);") + public static native void createAsyncHttpRequest(String method, String url, String body, HttpRequestCallback callback); + + @JSFunctor + private interface HttpRequestCallback extends JSObject { + void apply(JSError error, String response); + } } diff --git a/src/main/java/com/limechain/utils/json/JsonUtil.java b/src/main/java/com/limechain/utils/json/JsonUtil.java index c0ed70dcb..92e7aaba5 100644 --- a/src/main/java/com/limechain/utils/json/JsonUtil.java +++ b/src/main/java/com/limechain/utils/json/JsonUtil.java @@ -4,6 +4,9 @@ public class JsonUtil { + // Prevents instantiation + private JsonUtil() {} + public static Object parseJson(String jsonString) { return new JsonParser(jsonString).parse(); } @@ -13,6 +16,6 @@ public static String stringify(Object object) { } public static String readJsonFromFile(String filePath) { - return HttpRequest.httpRequestSync("GET", filePath, null); + return HttpRequest.asyncHttpRequest("GET", filePath, null); } } diff --git a/src/main/webapp/js/http.js b/src/main/webapp/js/http.js index e487222a1..fe84da78a 100644 --- a/src/main/webapp/js/http.js +++ b/src/main/webapp/js/http.js @@ -1,15 +1,22 @@ -function httpRequestSync(method, url, body) { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, false); // false for synchronous request - xhr.setRequestHeader('Content-Type', 'application/json'); - if (method === 'POST' && body) { - xhr.send(body); - } else { - xhr.send(); - } - if (xhr.status === 200) { - return xhr.responseText; - } else { - throw new Error('Request failed with status ' + xhr.status); +async function asyncHttpRequest(method = 'GET', url, body = null, callback) { + try { + const response = await fetch(url, { + method: method, + headers: { + 'Content-Type': 'application/json' + }, + body: method === 'POST' ? body : undefined + }); + + if (!response.ok) { + callback(new Error(`Request failed with status: ${response?.status}`), null); + return; + } + + const result = await response.text(); + callback(null, result); + + } catch (error) { + callback(new Error(`Error during sending request: ${error?.message}`), null); } } \ No newline at end of file