La Promesse et l'Avenir sont des concepts complémentaires. L'Avenir est une valeur qui sera récupéré, bien, à un moment donné dans l'avenir et vous pouvez faire des trucs avec elle lorsque cet événement se produit. Il est, par conséquent, de le lire ou de point de terminaison d'un calcul - c'est quelque chose que vous récupérer une valeur à partir.
Une Promesse est, par analogie, l'écriture côté du calcul. Vous créez une promesse qui est l'endroit où vous allez mettre le résultat du calcul et de la promesse que vous obtenez un avenir qui sera utilisé pour lire le résultat qui a été mis dans la promesse. Lorsque vous allez remplir une Promesse, soit par l'échec ou le succès, vous réalisez tous les comportements qui était attachée au Futur associé.
Concernant votre première question, comment peut-il être que pour une promesse p nous avons p.future == p
. Vous pouvez imaginer cela comme un simple élément de la mémoire tampon d'un conteneur qui est initialement vide et vous pouvez ensuite stocker une valeur qui deviendra son contenu à tout jamais. Maintenant, selon votre point de vue c'est à la fois une Promesse et un Avenir. C'est la promesse pour quelqu'un qui a l'intention d'écrire la valeur dans la mémoire tampon. C'est un avenir pour quelqu'un qui attend que la valeur à mettre dans la mémoire tampon.
Plus précisément, pour la Scala simultanées de l'API, si vous jetez un oeil à la Promesse de trait dans ici vous pouvez voir comment les méthodes de la Promesse compagnon objet sont mis en œuvre :
object Promise {
/** Creates a promise object which can be completed with a value.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]()
/** Creates an already completed Promise with the specified exception.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
/** Creates an already completed Promise with the specified result.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
}
Maintenant, ceux de la mise en œuvre des promesses, DefaultPromise et KeptPromise peut être trouvé ici. Ils ont à la fois d'étendre une base petit trait qui arrive à avoir le même nom, mais il est situé dans un package différent:
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
Donc vous pouvez voir ce qu'ils entendent par p.future == p
.
DefaultPromise
est le tampon je faisais allusion ci-dessus, tandis que d' KeptPromise
est un tampon avec la valeur mis en depuis sa création.
Quant à votre exemple, l'avenir de bloc que vous utilisez, il crée en fait une promesse derrière les coulisses. Regardons la définition de l' future
en ici :
def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body)
En suivant la chaîne de méthodes vous vous retrouvez dans l' impl.Avenir:
private[concurrent] object Future {
class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()
override def run() = {
promise complete {
try Success(body) catch { case NonFatal(e) => Failure(e) }
}
}
}
def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] = {
val runnable = new PromiseCompletingRunnable(body)
executor.execute(runnable)
runnable.promise.future
}
}
Donc, comme vous pouvez le voir, le résultat que vous obtenez à partir de votre producteur bloc obtient versé dans une promesse.
ÉDITER PLUS TARD:
Quant à l'utilisation dans le monde réel: la Plupart du temps vous n'aurez pas à traiter avec des promesses directement. Si vous allez utiliser une bibliothèque qui effectue le calcul asynchrone ensuite, vous aurez juste à travailler avec les contrats à terme renvoyé par la bibliothèque de méthodes. Les promesses sont, dans ce cas, créé par la bibliothèque, vous êtes juste à travailler avec la lecture de la fin de ce que ces méthodes ne.
Mais si vous avez besoin de mettre en place votre propre asynchrone API, vous aurez à commencer à travailler avec eux.
Supposons que vous avez besoin pour mettre en œuvre un async HTTP client sur le dessus, disons, de Netty. Puis votre code va ressembler à quelque chose comme ceci
def makeHTTPCall(request: Request): Future[Response] = {
val p = Promise[Response]
registerOnCompleteCallback(buffer => {
val response = makeResponse(buffer)
p success response
})
p.future
}