All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalajs.js.Thenable.scala Maven / Gradle / Ivy

The newest version!
/*
 * Scala.js (https://www.scala-js.org/)
 *
 * Copyright EPFL.
 *
 * Licensed under Apache License 2.0
 * (https://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

package scala.scalajs.js

import scala.language.implicitConversions

import scala.scalajs.js
import scala.scalajs.js.annotation._

import scala.concurrent.Future

/** A thing on which one can call the `then` method.
 *
 *  `Thenable`s are automatically transitively flattened by the `then` method
 *  of `Thenable`s. In particular, this is true for [[Promise]]s.
 *
 *  Attention! The nature of this interface, from the ECMAScript specification,
 *  makes it inherently un-typeable, because it is not type parametric.
 *
 *  The signature of the `then` method is only valid provided that the
 *  values of `B` do not have a `then` method.
 */
trait Thenable[+A] extends js.Object {
  def `then`[B](
      onFulfilled: js.Function1[A, B | js.Thenable[B]],
      onRejected: js.UndefOr[js.Function1[scala.Any, B | js.Thenable[B]]]): js.Thenable[B]

  def `then`[B >: A](
      onFulfilled: Unit,
      onRejected: js.UndefOr[js.Function1[scala.Any, B | js.Thenable[B]]]): js.Thenable[B]
}

object Thenable {
  implicit class ThenableOps[+A] private[Thenable] (
      private val p: js.Thenable[A])
      extends AnyVal {

    /** Converts the [[Thenable]] into a Scala [[scala.concurrent.Future Future]].
     *
     *  Unlike when calling the `then` methods of [[Thenable]], the resulting
     *  [[scala.concurrent.Future Future]] is always properly typed, and
     *  operations on it will be well-typed in turn.
     */
    def toFuture: Future[A] = {
      val p2 = scala.concurrent.Promise[A]()
      p.`then`[Unit](
          { (v: A) =>
            p2.success(v)
            (): Unit | js.Thenable[Unit]
          },
          js.defined { (e: scala.Any) =>
            p2.failure(js.special.wrapAsThrowable(e))
            (): Unit | js.Thenable[Unit]
          })
      p2.future
    }
  }

  /** Implicits for [[js.Thenable]]s.
   *
   *  Import `Implicits._` to enable [[scala.concurrent.Future Future]]'s
   *  operations directly on [[js.Thenable]]s, without needing to convert them
   *  with [[ThenableOps.toFuture toFuture]].
   *
   *  Unlike the `then` methods in [[Thenable]],
   *  [[scala.concurrent.Future Future]]'s operations are always well-typed.
   */
  object Implicits {
    implicit def thenable2future[A](p: js.Thenable[A]): Future[A] =
      p.toFuture
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy