Skip to content

Commit e737780

Browse files
committed
Add AsyncCallback.{promise,init}
1 parent 5b8e62d commit e737780

File tree

2 files changed

+38
-14
lines changed

2 files changed

+38
-14
lines changed

core/src/main/scala/japgolly/scalajs/react/AsyncCallback.scala

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package japgolly.scalajs.react
22

3-
import japgolly.scalajs.react.internal.{catchAll, identityFn}
3+
import japgolly.scalajs.react.internal.{catchAll, identityFn, newJsPromise}
44
import scala.collection.generic.CanBuildFrom
55
import scala.concurrent.duration.FiniteDuration
66
import scala.concurrent.{ExecutionContext, Future}
@@ -16,6 +16,21 @@ object AsyncCallback {
1616
def apply[A](f: (Try[A] => Callback) => Callback): AsyncCallback[A] =
1717
new AsyncCallback(f)
1818

19+
def init[A, B](f: (Try[B] => Callback) => CallbackTo[A]): CallbackTo[(A, AsyncCallback[B])] =
20+
for {
21+
(ac, c) <- promise[B]
22+
a <- f(c)
23+
} yield (a, ac)
24+
25+
/** Create an AsyncCallback and separately provide the completion function.
26+
*
27+
* This is like Scala's promise, not the JS promise which is more like Scala's Future.
28+
*/
29+
def promise[A]: CallbackTo[(AsyncCallback[A], Try[A] => Callback)] =
30+
for {
31+
(p, pc) <- newJsPromise[A]
32+
} yield (fromJsPromise(p), pc)
33+
1934
def first[A](f: (Try[A] => Callback) => Callback): AsyncCallback[A] =
2035
new AsyncCallback(g => {
2136
var first = true
@@ -398,19 +413,10 @@ final class AsyncCallback[A] private[AsyncCallback] (val completeWith: (Try[A] =
398413
}
399414

400415
def asCallbackToJsPromise: CallbackTo[js.Promise[A]] =
401-
CallbackTo {
402-
new js.Promise[A]((respond: js.Function1[A | Thenable[A], _], reject: js.Function1[Any, _]) => {
403-
def fail(t: Throwable) =
404-
reject(t match {
405-
case js.JavaScriptException(e) => e
406-
case e => e
407-
})
408-
completeWith(t => Callback(t match {
409-
case Success(a) => respond(a)
410-
case Failure(e) => fail(e)
411-
})).runNow()
412-
})
413-
}
416+
for {
417+
(p, pc) <- newJsPromise[A]
418+
_ <- completeWith(pc)
419+
} yield p
414420

415421
def unsafeToFuture(): Future[A] =
416422
asCallbackToFuture.runNow()

core/src/main/scala/japgolly/scalajs/react/internal/package.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package japgolly.scalajs.react
22

33
import scala.collection.generic.CanBuildFrom
44
import scala.collection.mutable.Builder
5+
import scala.scalajs.js
6+
import scala.scalajs.js.{Thenable, |}
57
import scala.util.{Failure, Success, Try}
68

79
package object internal {
@@ -35,4 +37,20 @@ package object internal {
3537
}
3638
}
3739
}
40+
41+
def newJsPromise[A]: CallbackTo[(js.Promise[A], Try[A] => Callback)] = CallbackTo {
42+
var complete: Try[A] => Callback = null
43+
val p = new js.Promise[A]((respond: js.Function1[A | Thenable[A], _], reject: js.Function1[Any, _]) => {
44+
def fail(t: Throwable) =
45+
reject(t match {
46+
case js.JavaScriptException(e) => e
47+
case e => e
48+
})
49+
complete = {
50+
case Success(a) => Callback(respond(a))
51+
case Failure(e) => Callback(fail(e))
52+
}
53+
})
54+
(p, complete)
55+
}
3856
}

0 commit comments

Comments
 (0)