服务器通过angularjs(和Play Framework)发送的事件在提交后继续重新启动

服务器通过angularjs(和Play Framework)发送的事件在提交后继续重新启动,angularjs,playframework-2.0,server-sent-events,Angularjs,Playframework 2.0,Server Sent Events,我正在尝试使用Angular.js单页应用程序构建SSE,并将Play Framework作为后端。似乎每次我使用angular的$http提交注册时,EventSource都会重新连接。 因为我试图使UI流平滑,所以在连接时,我添加了通过SSE推送数据的功能,它发送客户端获取并呈现的整个注册列表。在更新(注册新用户等)时,SSE将发送整个列表以及更改(添加的注册人等),客户端可以通过事件类型告知需要做什么(以及如果需要)(将新注册人添加到呈现的列表)。但是,由于某些原因,我一直在获取提交后的日

我正在尝试使用Angular.js单页应用程序构建SSE,并将Play Framework作为后端。似乎每次我使用angular的$http提交注册时,EventSource都会重新连接。 因为我试图使UI流平滑,所以在连接时,我添加了通过SSE推送数据的功能,它发送客户端获取并呈现的整个注册列表。在更新(注册新用户等)时,SSE将发送整个列表以及更改(添加的注册人等),客户端可以通过事件类型告知需要做什么(以及如果需要)(将新注册人添加到呈现的列表)。但是,由于某些原因,我一直在获取提交后的日期,而不是更新事件

下面的代码: SSE连接(在角度控制器-coffeescript符号中):

服务器端代码:

  def getSSE = Action { implicit request =>
    Async {
      Receiver.join map { join =>
        Ok.feed(join._2 &> EventSource()).as("text/event-stream")
      }
    }
  }
接收人:

class Receiver extends Actor {


  val (enumerator, channel) = Concurrent.broadcast[JsValue]

  def receive = {
    case Connect => {
      sender ! Connected(enumerator)
    }

    case Save(newOne) => {
      MyDao.save(newOne) map { saved =>
        sender ! ActionSuccess("New one Created", Some(saved))
        self ! notifyAll("Added", Some(saved)
      }
    }

    case NoOpUpdate(eventType, affectedOne) => {
      notifyAll("NoOpUpdate: " + eventType, affectedOne)
    }
  }

  def notifyAll(eventType: String, affectedOne: Option[Person]) {
    MyDao.findAll map { people =>
      val msg = JsObject(
        Seq(
          "type" -> JsString(eventType),
          "affectedOne" -> Json.toJson(affectedOne),
          "list" -> Json.toJson(people)
        )  
      )
      channel.push(msg)
    }
  }
}

object Receiver {
  val default = Akka.system.actorOf(Props[Receiver])
  implicit val timeout = Timeout(1 second)

  def update(eventType: String, affectedOne: Option[Person] = None) {
    default ! NoOpUpdate(eventType, affectedOne)
  }

  def join: Future[(Iteratee[JsValue,_],Enumerator[JsValue])] = {
    default ? Connect map {
      case Connected(enumerator) => {
        val iteratee = Iteratee.foreach[JsValue]{ js => 
          Json.stringify(js \ "type") match {
            case "save" => {
              Json.fromJson[Person](js \ "person").asOpt map { jsOpt => 
                default ? Save(jsOpt)                
              }
            }
            case _ => {

            }
          } 
        }
        (iteratee, enumerator)
      }
    }
  }
MyDAO:

  def save(person: Person): Future[Person] = {
    collection.save(person).map {
      case ok if ok.ok =>
        person
      case error => throw new RuntimeException(error.message)
    }
  }  

  def findAll: Future[Seq[Guardian]] = {
    collection.find(Json.obj())
      .sort(Json.obj("_id" -> -1))
      .cursor[Guardian]
      .toList
  }

很多代码和一个很长的问题。有什么想法吗?

不是100%确定它为什么要关闭,但看看这个:

$scope.serverListener.addEventListener('message', $scope.sseMessage, false)
您正在订阅类型为
message
(类似于
open
)的邮件。但是您发送的任何消息都没有发送类型(在JSON中设置名为
type
的属性并不发送类型)。要发送类型,您需要实现一个
play.api.libs.EventSource.EventNameExtractor
,它将从事件中提取名称。通常我会这样做:

然后我让我的枚举器成为这些事件类型的枚举器

另外,我希望您知道,您从未使用在join方法中创建的iteratee。也许你也在把它用于WebSocket,如果是这样的话,那没关系

不管怎样,要调试它关闭的原因。。。浏览器中开发人员控制台的“网络”选项卡上显示了什么

class Receiver extends Actor {


  val (enumerator, channel) = Concurrent.broadcast[JsValue]

  def receive = {
    case Connect => {
      sender ! Connected(enumerator)
    }

    case Save(newOne) => {
      MyDao.save(newOne) map { saved =>
        sender ! ActionSuccess("New one Created", Some(saved))
        self ! notifyAll("Added", Some(saved)
      }
    }

    case NoOpUpdate(eventType, affectedOne) => {
      notifyAll("NoOpUpdate: " + eventType, affectedOne)
    }
  }

  def notifyAll(eventType: String, affectedOne: Option[Person]) {
    MyDao.findAll map { people =>
      val msg = JsObject(
        Seq(
          "type" -> JsString(eventType),
          "affectedOne" -> Json.toJson(affectedOne),
          "list" -> Json.toJson(people)
        )  
      )
      channel.push(msg)
    }
  }
}

object Receiver {
  val default = Akka.system.actorOf(Props[Receiver])
  implicit val timeout = Timeout(1 second)

  def update(eventType: String, affectedOne: Option[Person] = None) {
    default ! NoOpUpdate(eventType, affectedOne)
  }

  def join: Future[(Iteratee[JsValue,_],Enumerator[JsValue])] = {
    default ? Connect map {
      case Connected(enumerator) => {
        val iteratee = Iteratee.foreach[JsValue]{ js => 
          Json.stringify(js \ "type") match {
            case "save" => {
              Json.fromJson[Person](js \ "person").asOpt map { jsOpt => 
                default ? Save(jsOpt)                
              }
            }
            case _ => {

            }
          } 
        }
        (iteratee, enumerator)
      }
    }
  }
  def save(person: Person): Future[Person] = {
    collection.save(person).map {
      case ok if ok.ok =>
        person
      case error => throw new RuntimeException(error.message)
    }
  }  

  def findAll: Future[Seq[Guardian]] = {
    collection.find(Json.obj())
      .sort(Json.obj("_id" -> -1))
      .cursor[Guardian]
      .toList
  }
$scope.serverListener.addEventListener('message', $scope.sseMessage, false)