My PlayFramework Action returns before a Future is ready, how do I update a web page component?

≡放荡痞女 提交于 2019-12-11 20:38:10

问题


I have a Scala PlayFramework function that calls MongoDB and gets a Future[Seq[Document]] result. After a map zoom/pan event, this Play Action function is called from JavaScript on a web page via xhttp/GET. My Action method on the Play side returns before the Future's onComplete/Success is executed. So I'm looking for a way to call a JavaScript function to get the data when the Scala Future's onComplete/Success fires. How would I do that, or am I looking at this wrong?

Here is the code in question.

def rect(swLon: Float, swLat: Float, neLon: Float, neLat: Float) = Action {
  val sb = new StringBuilder()
  sb.append("<tt>boundingBox: swLon=" + swLon + ", swLat=" + swLat + ", neLon=" + neLon + ", neLat=" + neLat + "</tt>")
  if (oDb.isDefined) {
    val collection: MongoCollection[Document] = oDb.get.getCollection(collectionName)
    val fut = getFutureOne(collection) // returns a Future[Seq[Document]]
    fut onComplete {
      case Success(docs) => { for (doc <- docs) { setMongoJson(doc.toJson } }
      case Failure(t) => { println("FAIL: " + t.getMessage) }
    }
  }
  Ok(sb.toString)
}

// below is temporary until I figure out a better way to store/return the result when it comes in
private var mongoJson: String = ""
private def setMongoJson(s: String): Unit = mongoJson = s

getFutureOne is temporary, it just does a db.collection.find().first().toFuture. I just wanted to make sure my connection to MongoDB was working, and it is. In actual fact I'll replace it with a query to return data that falls within the bounding box.


回答1:


Action is not designed to work with futures. Use Action.async, which will "wait" (technically not wait, but schedule) for the future to finish:

def rect(swLon: Float, swLat: Float, neLon: Float, neLat: Float) = Action.async {
  val sb = new StringBuilder()
  sb.append("<tt>boundingBox: swLon=" + swLon + ", swLat=" + swLat + ", neLon=" + neLon + ", neLat=" + neLat + "</tt>")
  if (oDb.isDefined) {
    val collection: MongoCollection[Document] = oDb.get.getCollection(collectionName)
    val fut = getFutureOne(collection) // returns a Future[Seq[Document]]
    fut.map {docs => 
      setMongoJson(doc.toJson)
      Ok(sb.toString)
    } recover {
      case e => BadRequest("FAIL: " + e.getMessage)
    }
  } else Future.successful(Ok("Not defined"))
}

Take a look at this for reference: https://www.playframework.com/documentation/2.4.x/ScalaAsync



来源:https://stackoverflow.com/questions/35185074/my-playframework-action-returns-before-a-future-is-ready-how-do-i-update-a-web

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!