Unable to use futures in scala.js - Rhino was unable to load the scala.js class

When I use futures in Scala.js, at least in tests, they never get executed and I can't wait for them.

Given this simple test:

package example

import utest._
import utest.framework.{Test, TestSuite}
import utest.util.Tree

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.language.postfixOps
import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue

object SomeFutureTest extends TestSuite {
  override def tests: Tree[Test] =
    TestSuite {
      'runs_future {
        val eventualString: Future[String] = Future[String] {
          "foo"
        }
        Await.result(eventualString, 5 seconds)
      }
    }
}

      

when i run test

on sbt console i get:

JavaException: org.scalajs.jsenv.rhino.ScalaJSCoreLib$ClassNotFoundException:
  Rhino was unable to load Scala.js class: ju_concurrent_locks_AbstractQueuedSynchronizer

      

when i do a nasty hack instead of Await

this:

while(!future.isCompleted) {}

      

it works forever.

Doesn't Await work in Scala.js? Can't you use futures and Await

their results in tests?

EDIT: it works with scala.scalajs.concurrent.JSExecutionContext.Implicits.runNow

instead queue

, but this calls futures in sync.

+3


source to share


1 answer


Really Await

doesn't work in Scala.js. It cannot, since it is a blocking API and there is no such thing as blocking in the JS framework.

For this reason, test environments are supported in a Future

special way by allowing the test itself to return Future

its execution. The test framework is then responsible for maintaining the asynchrony until the final display of the unit test results.

As documented in its Readme , uTest supports this. In your case, this will give:



TestSuite {
  'runs_future {
    val eventualString: Future[String] = Future[String] {
      "foo"
    }
    for (theString <- eventualString) yield {
      assert(theString == "foo")
      // and/or:
      theString
    }
  }
}

      

If you're more comfortable with the notation map

, here's the equivalent:

TestSuite {
  'runs_future {
    val eventualString: Future[String] = Future[String] {
      "foo"
    }
    eventualString map { theString =>
      assert(theString == "foo")
      // and/or:
      theString
    }
  }
}

      

+2


source







All Articles