qed qed - 3 months ago 28
Scala Question

"Cannot find an implicit ExecutionContext" error in scala.js example app.

Here is an example from the Hands-on Scala.js ebook:

package webpage

import org.scalajs.dom.ext.Ajax

import scala.scalajs.js
import scala.scalajs.js.annotation.JSExport
import scalatags.JsDom.all._
import org.scalajs.dom
import dom.html

@JSExport
object HelloWorld1 extends {
@JSExport
def main(target: html.Div) = {

lazy val box = input(
`type`:="text",
placeholder:="Type here!"
).render

lazy val output = div(
height:="400px",
overflowY:="scroll"
).render

box.onkeyup = (e: dom.Event) => {
output.innerHTML = "Loading..."
fetchWeather(box.value)
}

target.appendChild(
div(
h1("Weather Search"),
p(
"Enter the name of a city to pull the ",
"latest weather data from api.openweathermap.com!"
),
p(box),
hr, output, hr
).render
)

def fetchWeather(query: String) = {
val searchUrl =
"http://api.openweathermap.org/data/" +
"2.5/find?type=like&mode=json&q=" +
query

for{
xhr <- Ajax.get(searchUrl)
if query == box.value
} js.JSON.parse(xhr.responseText).list match{
case jsonlist: js.Array[js.Dynamic] =>
output.innerHTML = ""
showResults(jsonlist, query)
case _ =>
output.innerHTML = "No Results"
}
}
def showResults(jsonlist: js.Array[js.Dynamic], query: String) = {
for (json <- jsonlist) {
val name = json.name.toString
val country = json.sys.country.toString
val weather = json.weather.pop().main.toString

def celsius(kelvins: js.Dynamic) = {
kelvins.asInstanceOf[Double] - 273.15
}.toInt

val min = celsius(json.main.temp_min)
val max = celsius(json.main.temp_max)
val humid = json.main.humidity.toString
val (first, last) = name.splitAt(query.length)
output.appendChild(
div(
b(span(first, backgroundColor:="yellow"), last, ", ", country),
ul(
li(b("Weather "), weather),
li(b("Temp "), min, " - ", max),
li(b("Humidity "), humid, "%")
)
).render
)
}
}
}
}


Got an error when compiling:

[info] Compiling 1 Scala source to /Users/kaiyin/personal_config_bin_files/workspace/workbench-example-app/target/scala-2.11/classes...
[error] /Users/kaiyin/personal_config_bin_files/workspace/workbench-example-app/src/main/scala/HelloWorld1.scala:51: Cannot find an implicit ExecutionContext. You might pass
[error] an (implicit ec: ExecutionContext) parameter to your method
[error] or import scala.concurrent.ExecutionContext.Implicits.global.
[error] if query == box.value
[error] ^
[warn] /Users/kaiyin/personal_config_bin_files/workspace/workbench-example-app/src/main/scala/HelloWorld1.scala:53: non-variable type argument scala.scalajs.js.Dynamic in type pattern scala.scalajs.js.Array[scala.scalajs.js.Dynamic] is unchecked since it is eliminated by erasure
[warn] case jsonlist: js.Array[js.Dynamic] =>
[warn] ^
[warn] one warning found
[error] one error found
[info] workbench: Checking example-fastopt.js
[info] workbench: Checking webpage-fastopt.js
[error] (compile:compile) Compilation failed
[error] Total time: 0 s, completed 7 sept. 2015 12:51:38
78. Waiting for source changes... (press enter to interrupt)


What went wrong here?

Answer

As the error suggests, add the following imports:

import scala.concurrent._
import ExecutionContext.Implicits.global

or define an execution context implicitly that is in scope. You can define your own execution context as follows if you don't agree with the Typesafe default (ForkJoin pool):

import scala.concurrent._
val numberOfCPUs = sys.runtime.availableProcessors()
val threadPool = Executors.newFixedThreadPool(numberOfCPUs)
implicit val ec = ExecutionContext.fromExecutorService(threadPool)
Comments