Question

I want to show future response in UI in a liftweb framework.

Following is a Loggable snippet method(processRequest) I'm currently using to respond back future object to UI textarea using SetHtml but blocking with Thread.sleep

 27 def render = {

 45  def processRequest() : JsCmd = {                                                                
 46                                                                                                     
 47       val future_ : LAFuture[String] = new LAFuture()                                               
 48                                                                                                     
 49       val urlRequest = url(request)                                                                 
 51       val future = Http(urlRequest OK as.String)                                                                                                                                
 57                                                                                                     
 58       future onSuccess {                                                                            
 59               case json =>                                                                          
 60                 resp = json                                                                         
 61                 logger.info(s"[onSuccess] response => ${json}")                                     
 62                 SetHtml("response", Text(resp+"")) //FIXME                                          
 63                 logger.info(s"[onSuccess] response => ${json}") //works fine                                     
 64                                                                                                     
 65       }                                                                                             
 66                                                                                                     
 67       future onFailure {                                                                            
 68               case exception =>                                                                     
 69                 logger.info(s"${exception.getMessage()}")                                           
 70       }                                                                                             
 71       Thread.sleep(2000) //TEMPORARY FIX                                                                           
 72       logger.info("[outside] response => ${resp}")                                                  
 73       SetHtml("response", Text(resp))  //it works in blocking mode                                                             
 74   }            

 77     "@requestid"  #> text(requestid, s => requestid = s) &                                          
 78     "@request"    #> text(request  , s => request = s) &                                            
 79     "@response"   #> textarea(responseString, s=>responseString = s) &                                                                            
 81     "@processreq" #> ajaxSubmit("Send Request", processRequest) 
 75  }

SetHtml doesn't work inside onSuccess, though I get json there. SetHtml has following doc,

Replaces the content of the node with the provided id with the markup given by content

This is analogous to assigning a new value to a DOM object's innerHtml property in Javascript.

I have all this app available at github.

What I want is solution to SetHtml in handling future object where the request itself is through ajax.

Was it helpful?

Solution

SetHtml returns a JsCmd, but in order for that to be sent to the browser it would need to be part of a server response. However, as you are calling it asynchronously there is no response to send it with and therefore the browser never receives it. To fix that you have two options:

  1. Wait for the future to finish by blocking, something like having your function return future.get
  2. Use an actor which allows for server push communication with the browser. In that way, your future could send a message to the actor upon completion and then the actor would send the setHtml command.

There is a quick example with Lift actors here (unfortunately uses the old bind syntax in render) which illustrates how to send a message and have that execute setHtml: https://www.assembla.com/wiki/show/liftweb/Comet_Support

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top