Вопрос по sync, synchronous, asynchronous, gwt, jsni – GWT Синхронный звонок
У меня есть метод в GWT, который извлекает ДАННЫЕ из БД, используя метод огня запросов, поскольку вы все знаете, что он асинхронный. Я вызываю этот метод из 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 [email protected]::retriveLocation(Ljava/lang/String;);
}-*/;
и внутриonModuleLoad()
Я звонюexportStaticMethod()
.
и в HTML у меня есть кнопка, которую я вызываю onclickgetAutocomplete()
как это:
<input type="button" onclick="alert(getAutocomplete('j'))" value="momo" />
Проблема в том, что размер всегда возвращает 0, потому что метод асинхронный, но если бы я мог вернуть значениеonSuccess
это решило бы мою проблему. Есть идеи, пожалуйста? Я гуглил это в течение 2 дней и не получил ответа.
Другими словами:
У меня есть метод JS, он мне нужен для вызова метода Java, чтобы получить данные из БД, но синхронно!
пример
Если у меня есть кнопка HTML и при нажатии, я передам идентификатор функции, и мне нужно получить имя из БД через GWT и предупредить его; просто потому, что GWT является асинхронным, я не смогу делать это каждый раз, и когда я сообщу результат, он будет пустым, потому что он еще не заполнен.
Ахмад, ссылаясь на приведенный вами пример:
Вызовите функцию при нажатии, скажем, «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());
}
}
GWT не позволяет выполнять синхронные вызовы на сервер, так как они могут заставить ваш браузер зависать до тех пор, пока он не получит ответ, поэтому по понятным причинам лучше, если вы можете изменить поток так, чтобы результат от сервера обрабатывался внутриonSuccess
обработчик события.
my business need is to make a JS function retrieve data from DB but IT MUST BE SYNCHRONOUS
Вы можете получать данные из базы данных только через Java (или используя любой другой серверный язык), но не используя JavaScript. Просто сделайте асинхронный вызов из GWT, используя либоRequestBuilder
или механизм GWT RPC. Возвращенные данные могут быть обработаны внутри соответствующих обработчиков, как уже упоминалось.
От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.open ().
Вы не можете использовать собственный GWT RPC синхронно. Я не уверен, что это то, что вы спрашиваете, но вот как сделать синхронный вызов на сервер:
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;
}-*/;
Обратите внимание, что я не обсуждаю, хорошая это идея или нет. Вы, вероятно, должны придерживаться Async и поставить предупреждение на событие успеха.