2016-01-18 3 views
11

मेरे जीडब्ल्यूटी एप्लीकेशन में मैं अक्सर एक ही सर्वर परिणामों में कई बार refering कर रहा हूँ। मुझे यह भी नहीं पता कि कौन सा कोड पहले निष्पादित किया गया है। इसलिए मैं अपने एसिंक्रोनस (क्लाइंट-साइड) परिणामों के कैशिंग का उपयोग करना चाहता हूं।अमरूद के साथ जीडब्ल्यूटी में सर्वर परिणामों को कैसे कैश करें?

मैं मौजूदा कैशिंग लाइब्रेरी का उपयोग करना चाहता हूं; मैं guava-gwt पर विचार कर रहा हूं।

मैं (guava's documentation में) एक अमरूद तुल्यकालिक कैश के इस उदाहरण पाया:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() 
     .build(
      new CacheLoader<Key, Graph>() { 
      public Graph load(Key key) throws AnyException { 
       return createExpensiveGraph(key); 
      } 
      }); 

इस तरह मैं एक अमरूद कैश एसिंक्रोनस रूप (मैं के बारे में कोई सुराग नहीं कैसे करने के लिए है का उपयोग करने के कोशिश कर रहा हूँ है)

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() 
     .build(
      new CacheLoader<Key, Graph>() { 
      public Graph load(Key key) throws AnyException { 

       // I want to do something asynchronous here, I cannot use Thread.sleep in the browser/JavaScript environment. 
       service.createExpensiveGraph(key, new AsyncCallback<Graph>() { 

       public void onFailure(Throwable caught) { 
        // how to tell the cache about the failure??? 
       } 

       public void onSuccess(Graph result) { 
        // how to fill the cache with that result??? 
       } 
       }); 

       return // I cannot provide any result yet. What can I return??? 
      } 
      }); 

GWT डिफ़ॉल्ट JRE से कई वर्गों याद आ रही है (विशेष रूप से धागे और concurrancy के विषय में: यह काम कर रहे हैं)।

मैं एसिंक्रोनस परिणामों को कैश करने के लिए guava-gwt का उपयोग कैसे कर सकता हूं?

उत्तर

5

के रूप में मैं समझ गया कि आप क्या हासिल करना चाहते हैं सिर्फ एक नहीं है एसिंक्रोनस कैश लेकिन एक आलसी कैश बनाने के लिए और एक जीडब्ल्यूटी बनाने के लिए सबसे अच्छी जगह नहीं है क्योंकि क्लाइंट साइड असिंक्रोनस निष्पादन के साथ जीडब्ल्यूटी ऐप को कार्यान्वित करते समय बड़ी समस्या होती है, क्योंकि जीडब्ल्यूटी में क्लाइंट की कमी होती है Future एस और/या आरएक्स घटकों के पक्ष कार्यान्वयन (अभी भी जीडब्ल्यूटी के लिए आरएक्सजेवा के कुछ कार्यान्वयन हैं)। तो हमेशा की तरह जावा में क्या आप बनाना चाहते हैं के द्वारा प्राप्त किया जा सकता है:

LoadingCache<String, Future<String>> graphs = CacheBuilder.newBuilder().build(new CacheLoader<String, Future<String>>() { 
    public Future<String> load(String key) { 
     ExecutorService service = Executors.newSingleThreadExecutor(); 
     return service.submit(()->service.createExpensiveGraph(key)); 
    } 
}); 
Future<String> value = graphs.get("Some Key"); 
if(value.isDone()){ 
    // This will block the execution until data is loaded 
    String success = value.get();   
} 

लेकिन तुम जैसे

public class FutureResult<T> implements AsyncCallback<T> { 
    private enum State { 
     SUCCEEDED, FAILED, INCOMPLETE; 
    } 

    private State state = State.INCOMPLETE; 
    private LinkedHashSet<AsyncCallback<T>> listeners = new LinkedHashSet<AsyncCallback<T>>(); 
    private T value; 
    private Throwable error; 

    public T get() { 
     switch (state) { 
     case INCOMPLETE: 
      // Do not block browser so just throw ex 
      throw new IllegalStateException("The server response did not yet recieved."); 
     case FAILED: { 
      throw new IllegalStateException(error); 
     } 
     case SUCCEEDED: 
      return value; 
     } 
     throw new IllegalStateException("Something very unclear"); 
    } 

    public void addCallback(AsyncCallback<T> callback) { 
     if (callback == null) return; 
     listeners.add(callback); 
    } 

    public boolean isDone() { 
     return state == State.SUCCEEDED; 
    } 

    public void onFailure(Throwable caught) { 
     state = State.FAILED; 
     error = caught; 
     for (AsyncCallback<T> callback : listeners) { 
      callback.onFailure(caught); 
     } 
    } 

    public void onSuccess(T result) { 
     this.value = result; 
     state = State.SUCCEEDED; 
     for (AsyncCallback<T> callback : listeners) { 
      callback.onSuccess(value); 
     } 
    } 

} 

और अपने कार्यान्वयन हो जाएगा बनाने की आवश्यकता के रूप में GWT Future रों लिए कोई कार्यान्वयन है:

LoadingCache<String, FutureResult<String>> graphs = CacheBuilder.newBuilder().build(new CacheLoader<String, FutureResult<String>>() { 
     public FutureResult<String> load(String key) { 
      FutureResult<String> result = new FutureResult<String>(); 
      return service.createExpensiveGraph(key, result); 
     } 
    }); 

    FutureResult<String> value = graphs.get("Some Key"); 

    // add a custom handler 
    value.addCallback(new AsyncCallback<String>() { 
     public void onSuccess(String result) { 
      // do something 
     } 
     public void onFailure(Throwable caught) { 
      // do something    
     } 
    }); 
    // or see if it is already loaded/do not wait 
    if (value.isDone()) { 
     String success = value.get(); 
    } 

का उपयोग करते समय FutureResult तुम सिर्फ निष्पादन को कैश नहीं होगा, लेकिन यह भी तो तुम कुछदिखा सकते हैं आलस्य किसी तरह मिलजबकि डेटा कैश में लोड किया गया है।

+0

जो आप चाहते हैं वह कार्यान्वित करना मुश्किल नहीं है, यह सफलतापूर्वक कॉलबैक हैंडलर को 'फ्यूचर रीसेट' में जोड़ने के लिए है। मैं अपने विचार को प्रतिबिंबित करने के लिए एक स्रोत कोड उदाहरण अपडेट करूंगा। लेकिन आपको समझना चाहिए कि कॉलबैक को केवल पहले लोड पर एक बार बुलाया जाएगा (जिसे कैश किया जाएगा)। तो कॉलबैक के बाद '' result.isDone'' सत्य होगा। – Babl

+0

इसके बजाय CompletableFuture देखें - यह वादा की तरह अधिक व्यवहार करता है, हालांकि अगर किसी भी अवरोध भविष्य के तरीकों का उपयोग करता है तो आपको अपवाद फेंकने की आवश्यकता होगी। –

+0

@ColinAlworth GWT समर्थन 'CompletableFuture' करता है? – Babl

0

तुम सिर्फ अतुल्यकालिक कॉल परिणाम कैश करने के लिए की जरूरत है, तो आप एक गैर लोड हो रहा है कैश के लिए, एक लोड हो रहा है कैश

के बजाय जा सकते हैं इस मामले आप डाल उपयोग करने की आवश्यकता में, getIfPresent तरीकों कैश से रिकॉर्ड स्टोर और पुनर्प्राप्त करने के लिए।

String v = cache.getIfPresent("one"); 
// returns null 
cache.put("one", "1"); 
v = cache.getIfPresent("one"); 
// returns "1" 

वैकल्पिक रूप से एक नया मान एक प्रतिदेय कैश पर से लोड किया जा सकता याद करते हैं

String v = cache.get(key, 
    new Callable<String>() { 
     public String call() { 
     return key.toLowerCase(); 
    } 
}); 

आगे के संदर्भ के लिए: https://guava-libraries.googlecode.com/files/JavaCachingwithGuava.pdf

+0

यह वह नहीं था जिसे मैं ढूंढ रहा था। पहला उदाहरण केवल कुंजी द्वारा मूल्यों को संग्रहीत करने में मदद करेगा, लेकिन डेटा लोड करने के लिए कोई सहायता प्रदान नहीं करेगा। दूसरा उदाहरण सिंक्रोनस लोडिंग को संभालने में सक्षम होगा। – slartidan

+0

मैंने सोचा था कि जब आप एसिंक्रोनस कॉल बैक पर 'असफल' में पहुंच जाएंगे तो आप परिणाम को कैश में डाल सकते हैं। – Hari

संबंधित मुद्दे