Calling an External Javascript API from Scala.js
In which I show to how to call native Javascript APIs in Scala and Scala.js, using gapi.auth.authorize as an example
I recently started a new project, and since I love Scala, I thought it would be cool to write the whole webapp in the language. Thanks to Scala.js, it seems like this dream will be possible. Github user vmunier
already has a great repo that shows how to integrate Play Framework and Scala.js, so I’ll refer you to that if you’re looking to get started.
Shortly after starting this project, I needed to use Google’s Javascript API, and therefore also had to find out how to call Javascript from Scala.js. Scala.js’s documentation on the subject explains how to do it, but in order to more fully understand the subject, I decided I would write a more detailed explanation, as well as explain how to pass messages to the Javascript API. In this post, I will call gapi.auth.authorize
as an example, and will be working from Google’s Drive API example.
Here’s what we’re trying to mimic with Scala.js:
Essentially, when the Google API script is loaded, we tell it to call handleClientLoad
, which then calls checkAuth
a second later.
The first step to making this work from Scala is to define a Scala binding for the Javascript API. We need to be able to call gapi.auth.authorize
. Scala.js defines Javascript objects with traits, so we’ll need the following:
For now, don’t worry about the types on the authorize
method. That will come later. Both of these traits extend js.Object
, and, as such, cannot contain values or methods that are not assigned js.native
. When compiled to Javascript, Gapi
will be a Javascript object that has a value called auth
, which in turn is an object that has a function called authorize
. However, to make it possible to use these objects in the global scope, we need the following:
Having an object that extends GlobalScope
will make it so that the members of the object represent global Javascript variables.
Next, we need to define a Scala interface for the messages passed to and from gapi.auth.authorize
.
Once again, we define Javascript objects with traits. The Authorize
trait defines the interface we use in Scala, while the companion object calls on js.Dynamic
to create the literal Javascript object that will be used in the browser. In order to maintain the type system in Scala, we cast the dynamic object that gets created to be an instance of Authorize
.
AuthorizeResult
just defines a Scala interface for the response from gapi.auth.authorize
. In the Scala binding for the authorize
function, we see that the type of the callback is js.Function1[AuthorizeResult, Unit]
. That means it’s a Javascript function that takes one parameter (which conforms to the interface defined by AuthorizeResult
) and returns no result.
Finally, it’s time to call the API from Scala!
The OAuth
object is very straight forward. We just call the API as we’ve defined it and provide a callback function that will print out the result. We also provide an OAuthBootstrap
object, and export it as OAuthBootstrap
(to avoid exporting that package name to Javascript). A call in Javascript to OAuthBootstrap()
will result in the body of this object being called. A second later, thanks to setTimeout
, we’ll call our Scala OAuth
object’s checkAuth
method, which will, in turn, call gapi.auth.authorize
.
That’s it! We’ve now called a Javascript API from Scala with Scala.js! Pretty cool stuff. Please let me know if you have any questions, or if I’ve written anything inaccurate here.
Update
Sébastien made a great suggestion: when defining the Scala binding for Javascript, use the JSName annotation to avoid creating a bunch of traits (and the package object), thus, the code example above would become the following:
Thanks to Sébastien for the help!
Comments
Let me know what you think!