2013-03-16 9 views
11

Devo implementare una funzione che chiama un servizio web e restituisce la risposta.Generatore di richieste Gwt - come restituire la stringa di risposta

ho cercato

public String getFolderJson(String path) { 
      String result="initial_value"; 
      StringBuilder param = new StringBuilder(); 
      param.append("?sessionId=").append(getSessionId()); 
      param.append("&path=").append(path); 
      RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, "https://localhost/folder" + param); 
        try { 
         builder.sendRequest(null, new RequestCallback() { 
         @Override 
         public void onResponseReceived(Request request, 
           Response response) { 
           result = response.getText(); 
           System.out.println(response.getText()); 
              //I need to return "result" 
         } 
         @Override 
         public void onError(Request request, Throwable exception) {} 
          }); 
        return result; //the result get returned before the response is recieved.So i am getting the return value "initial_value". 
        }  
        catch (RequestException e) {} 
     return null; 
    } 

A chiamare getFolderJson() servizio web viene chiamato con successo. Ma result viene restituito prima che venga ricevuto il respnse. Quindi sto ottenendo il valore di retunr "initial_value".
Come restituire il valore dalla risposta quando la funzione getFolderJson()?

risposta

5

GWT non supporta Ajax sincrono, quindi è necessario codificare l'app utilizzando un modello asincrono.

L'oggetto di livello basso che GWT utilizza per eseguire la richiesta è un XMLHttpRequest (eccetto per le vecchie versioni di IE) e GWT chiama sempre il metodo open() con async impostato su true. Quindi l'unico modo per avere ajax sincrono è mantenere la propria versione modificata di XMLHttpRequest.java. Ma l'ajax sincrono è una cattiva idea, e anche jQuery ha deprecato questa possibilità.

Quindi il modo normale in gwt dovrebbe essere che il metodo restituisce void e si passa un parametro aggiuntivo con un callback da eseguire quando la risposta è disponibile.

public void getFolderJson(String path, Callback<String, String> callback) { 
    RequestBuilder builder = new RequestBuilder(...); 
    try { 
     builder.sendRequest(null, new RequestCallback() { 
     @Override 
     public void onResponseReceived(Request request, Response response) { 
      callback.onSuccess(response.getText()); 
     } 
     @Override 
     public void onError(Request request, Throwable exception) {} 
      callback.onFailure(exception.getMessage()); 
     }); 
    } catch (RequestException e) { 
     callback.onFailure(exception.getMessage()); 
    } 
} 

Preferirei gwtquery Promises sintassi per questo invece di richiesta-builder uno:

Ajax.get("http://localhost/folder?sessionId=foo&path=bar") 
    .done(new Function(){ 
     public void f() { 
     String text = arguments(0); 
     } 
    }); 
+0

Ho un componente browser di file. Devo restituire il risultato di 'getFolderJson (...)' quando il componente richiede i dettagli del foder. Non posso farlo con il modello di callback. –

+0

Credo che ci siano modi per cambiare il tuo codice per usare i callback, questo è il modo in cui tutte le app RIA funzionano e ci sono un sacco o qualsiasi tipo di app. Magari potresti pubblicare un pezzo di codice più grande con la chiamata a 'getFolderJson' in modo da poter trovare una soluzione. Comunque nel caso in cui si continui a voler usare Ajax sincrono (cosa che scoraggio), copia semplicemente 'XMLHttpRequest.java' con il suo percorso completo nel tuo progetto e cambia la riga' this.open (httpMethod, url, true); 'con 'this.open (httpMethod, url, false);' –

1

Immagino che il builder.sendRequest (xxx) restituirà qualcosa come un futuro, e puoi ottenere il risultato da quell'oggetto. Quello che stai usando è un metodo asincrono di RequestBuilder, dovrebbe esserci anche un metodo sincrono.

da cosa proviene il RequestBuilder? Posso controllare l'api per te.

OK, provate questo:

public String getFolderJson(String path) { 
    String result = "initial_value"; 
    StringBuilder param = new StringBuilder(); 
    param.append("?sessionId=").append(getSessionId()); 
    param.append("&path=").append(path); 
    RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, 
      "https://localhost/folder" + param); 
    final SynchronousQueue resultQueue = new SynchronousQueue(); 
    try { 
     builder.sendRequest(null, new RequestCallback() { 
      @Override 
      public void onResponseReceived(Request request, 
        Response response) { 
       resultQueue.put(response.getText()); 
       System.out.println(response.getText()); 
      } 

      @Override 
      public void onError(Request request, Throwable exception) { 
      } 
     }); 
     return resultQueue.take(); 
    } catch (RequestException e) { 
    } 
    return result; 
} 

sembra RequestBuilder non ha alcun metodo sincrono per ottenere il risultato solo una richiamata.

Fare attenzione che questo metodo verrà bloccato fino a quando non viene ricevuta la risposta. Se questo metodo viene chiamato in un thread di elaborazione eventi di gwt, questa sarebbe una cattiva pratica.

+0

com.google.gwt.http.client.RequestBuilder –

+0

ottimizzarlo per renderlo più robusto: onError (xxx, xxx) {resultQueue.put (risultato); } e setTimeoutMillis (xxx) per assicurarsi che la richiesta non si blocchi per sempre. – BlackJoker

+4

@ Spring.Rush 'SynchronousQueue' non è supportato dal [gwt emulated jre] (https://developers.google.com/web-toolkit/doc/1.6/RefJreEmulation), quindi il tuo codice non verrà mai compilato in js. –

Problemi correlati