Passa il callback alla funzione per registrarti sul metodo scala future onComplete

Aug 23 2020

Dovevo usare il onCompletemetodo su una scala future, come descritto qui .

L'idea di base si presenta così:

def getPosts(url: String, callback: Try[HttpResponse[String]] => Unit) {
  val f: Future[[HttpResponse[String]]] = Future {
    val response: HttpResponse[String] = Http(url).get()
    if (response.code > 399) {
      throw new Exception(s"Error sending to ${url}")
    }

    response
  }

  f onComplete callback
}

val cb= {
  case Success(response : HttpResponse[String]) => succesfulWrites += 1
  case Failure(err) => totalFailedWrites += 1
}

getPosts("localhost:8000/widgets", cb)

Tuttavia, continuo a ricevere errori come missing parameter type for expanded function. The argument types of an anonymous function must be fully known.(per quanto riguarda la riga in cui definisco val onComplete) o altri errori simili che dicono che sto sbagliando.

Dato che sono nuovo su Scala, riconosco che potrei semplicemente fraintendere il modo migliore per farlo. Tuttavia, ho difficoltà a trovare esempi per quello che sembra essere un caso d'uso abbastanza comune. Sto pensando ai futures / callback in scala in modo errato? In caso contrario, esiste un semplice esempio end-to-end per questo scenario (passaggio di callback come arg in una funzione che utilizza futures)?

Risposte

1 MarioGalic Aug 23 2020 at 01:11

Il tipo previsto di pattern corrispondente alla funzione anonima

{
  case Success(response: HttpResponse[String]) => successfulWrites += 1
  case Failure(err)                            => totalFailedWrites += 1
}

deve essere specificato esplicitamente, quindi invece di

val cb = {
  case Success(response: HttpResponse[String]) => successfulWrites += 1
  case Failure(err)                            => totalFailedWrites += 1
}

dobbiamo scrivere qualcosa di simile

val cb: Try[HttpResponse[String]] => Unit = {
  case Success(response: HttpResponse[String]) => successfulWrites += 1
  case Failure(err)                            => totalFailedWrites += 1
}

Qui sto assumendo la firma di getPostsis

def getPosts(url: String, callback: Try[HttpResponse[String]] => Unit)

Più precisamente, solo il tipo di parametro (al contrario del tipo restituito dell'intero tipo di funzione) deve essere fornito esplicitamente, il che significa che anche quanto segue funzionerebbe

val cb = (x: Try[HttpResponse[String]]) => x match {
  case Success(response: HttpResponse[String]) => successfulWrites += 1
  case Failure(err)                            => totalFailedWrites += 1
}