Синхронный вызов GWT
У меня есть метод в GWT, который извлекает данные из БД, используя метод fire запросов, как вы все знаете, его асинхронный я вызываю этот метод из JS, поэтому мне нужно сделать синхронным возможно ли это
private static String retriveLocation(String part)
{
ClientFactory clientFactory = GWT.create(ClientFactory.class);
MyRequestFactory requestFactory = clientFactory.getRequestFactory();
YadgetRequest request = requestFactory.yadgetRequest();
String criteria = "!" + part;
final ArrayList<String> tags = new ArrayList<String>();
request.getTagsStartingWith(criteria, 10, 0).fire(
new Receiver<List<TagProxy>>() {
@Override
public void onSuccess(List<TagProxy> tagList) {
String output = "[";
for (TagProxy pt : tagList) {
output += "{";
output += ""id":" + """ + pt.getId() + "",";
output += ""value":"
+ """
+ pt.getName().replaceAll(""", "")
.replaceAll("!", "") + """;
output += "},";
}
if (output.length() > 2)
output = output.substring(0, output.length() - 1);
output += "]";
tags.add(output);
}
@Override
public void onFailure(ServerFailure error) {
}
});
return tags.size() + "";
}
И вызов этой функции из JS следующим образом:
public static native void exportStaticMethod() /*-{
$wnd.computeLoanInterest =
$wnd.getAutocomplete =@com.yadget.client.Yadget::retriveLocation(Ljava/lang/String;);
}-*/;
И внутри onModuleLoad()
я вызываю exportStaticMethod()
.
И в html у меня есть кнопка, которую я называю onclick getAutocomplete()
Вот так:
<input type="button" onclick="alert(getAutocomplete('j'))" value="momo" />
Проблема в том, что размер всегда возвращает 0, потому что метод асинхронно, но если бы я мог вернуть значение onSuccess
, это решило бы мою проблему. Есть идеи, пожалуйста? Я гуглил его в течение 2 дней и не получил никакого ответа.
Другими словами:
У меня есть метод JS, мне нужно, чтобы он вызывал метод java для извлечения данных из БД, но синхронно!
Пример
Если у меня есть кнопка HTML и при нажатии я передам ID функции, и мне нужно повторно создать имя из БД через GWT и предупредить его; просто потому, что GWT является асинхронным, я не смогу делайте это каждый раз, и когда я сообщу результат, он будет пустым, потому что он еще не заполнен.
4 ответа:
Вы не можете использовать собственный RPC GWT синхронно. Я не уверен, что это то, о чем вы спрашиваете, но вот как сделать вызов на сервер синхронно:
Пожалуйста, обратите внимание, что я не обсуждаю, является ли это хорошей идеей или нет. Вероятно, вам следует придерживаться асинхронности и поставить оповещение о событии успеха.private native String makeSyncAjaxCall(String url, String msgText, String conType)/*-{ var xhReq = new XMLHttpRequest(); xhReq.open(conType, url, false); if(conType == "POST") xhReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); xhReq.send(msgText); var serverResponse = xhReq.status + xhReq.responseText; return serverResponse; }-*/;
GWT не позволяет выполнять синхронные вызовы на сервер, так как они могут заставить ваш браузер зависнуть, пока он не получит ответ, поэтому по понятным причинам лучше всего, если вы можете изменить поток таким образом, что результат с сервера будет обработан внутри обработчика событий
onSuccess
.Моя бизнес-потребность состоит в том, чтобы сделать функцию JS извлекать данные из БД, но она должна быть синхронной
Вы можете получить данные из базы данных только через java (или используя любой другой серверный язык), но не с помощью JavaScript. Просто сделайте асинхронный вызов из GWT, используя либо
RequestBuilder
, либо механизм GWT RPC. Возвращенные данные могут быть обработаны внутри соответствующих обработчиков, как уже упоминалось.
Ахмад, ссылаясь на приведенный вами пример:
Вызовите функцию по щелчку, скажите "getNamefromID ()" в GWT , который делает асинхронный вызов БД и в функции onSuccess (), вызовите функцию, которая предупредит имя.
public void getNamefromID(int ID) { String postUrl = "http://mani/getName"; String requestData = "q=ID"; RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, postUrl); builder.setHeader("Access-Control-Allow-Origin", "*"); try { builder.sendRequest(requestData.toString(), new RequestCallback() { public void onError(Request request, Throwable e) { Window.alert(e.getMessage()); } public void onResponseReceived(Request request, Response response) { if (200 == response.getStatusCode()) { Window.alert("Name :" + response.getText()); } else { Window.alert("Received HTTP status code other than 200 : " + response.getStatusText() + "Status Code :" + response.getStatusCode()); } } }); } catch (RequestException e) { // Couldn't connect to server Window.alert(e.getMessage()); } }
Из https://stackoverflow.com/a/40610733/6017801 :
GWT вызывает XMLHttpRequest.open () с true в качестве третьего параметра, что означает, что вызов будет асинхронным. Я решил аналогичную задачу для целей тестирования, просто заставив этот третий параметр всегда быть ложным:
private static native void fakeXMLHttpRequestOpen() /*-{ var proxied = $wnd.XMLHttpRequest.prototype.open; (function() { $wnd.XMLHttpRequest.prototype.open = function() { arguments[2] = false; return proxied.apply(this, [].slice.call(arguments)); }; })(); }-*/;
После вызова fakeXMLHttpRequestOpen() любое дальнейшее использование XMLHttpRequest будет действовать синхронно. Например:
remoteSvc.getResult(new AsyncCallback<String>() { @Override public void onSuccess(String result) { GWT.log("Service called!"); } @Override public void onFailure(Throwable caught) { GWT.log("Service failed..."); } } GWT.log("Last message");
Будет всегда рендер:
Service called! Last message
См. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open для XMLHttpRequest.открытая спецификация.