Calling R functions through AJAX using opencpu.js
September 21, 2013
Getting started with opencpu.js
The readme page for opencpu.js has some brief documentation, but perhaps the easiest way to get started with opencpu.js is by example. The opencpu apps page lists a couple of example apps that you can play around with. The source code for each app is available from the opencpu github organization, and each app is based on opencpu.js. The appdemo app contains some pages with minimal examples illustrating the basic
opencpu.js functionality. Like all OpenCPU apps, you can either use it on the public cloud server, or install for local use:
Hello World: calling a function
The first line is basic jQuery syntax and reads the value from the page element with id
namefield down in the html. In the next line we use
ocpu.rpc to call the R function hello (included in the app package) and pass the value to the
myname argument of the R function. The final argument is the callback handler: a function to (asynchronously) processes the output once the request has returned from the server. In this case our callback handler writes
output$message value returned by our R function to the html field with id
Web developers will immediately recognize this pattern: all functions in the opencpu.js library wrap around the jQuery
$.ajax method and return the
jqXHR object. Thereby you (the programmer) have full control over the request using all methods and properties from jQuery.ajax. So you can register additional handlers to deal with errors or to add additional behavior after the request has completed (in the example to re-enable a button).
Making a plot
The opencpu.js library also makes it easy to embed your R plots in a website. The plot.html page illustrates this with a very simple example. Again, look at the source of the HTML page:
The syntax for is slightly different than when calling a function before: the plotting widget is implemented as a jQuery plugin and hence called on a dom element, usually an empty
<div>. In this case we call the R function randomplot (included with the appdemo package) and pass arguments
dist. Once completed, a png image of the plot is displayed in
#plotdiv and links to pdf and svg images.
Uploading a File
In many statistical applications the user needs to provide some data, often in the form of a file. When using opencpu.js, calling an R function with a file works exactly the same as calling it with any other value. Look at the source code for upload.html to see this in action.
Basically for any
<input type="file"> HTML element we can pass the file to an R function using
$("#id").files (note this requires HTML5 support). OpenCPU will then copy this file to the working directory of the R process and use the filename as the parameter value. The next section shows how we would actually use this object.
Simulating state by chaining function calls
Thus far all examples contained a single R function call and we would either grab the output or some plot to display on the page. However in practice your application might involve several steps: the user uploads some data, specifies variables, fits a model on the data, etc.
The OpenCPU API is stateless. Clients do not have a private R process and each call to the server is independent of the previous one. Instead, the way you can introduce state is by chaining function calls: the OpenCPU server stores the return object from a function call, and you can pass a reference to such an object as a argument to subsequent function calls. This might sound cumbersome at first, but it results in well organized, scalable applications and makes asynchronous parallel requests a native feature of your application.
This look very similar as before:
ocpu.call is used to call the R function readcsvnew. However this time the callback function calls another function by passing on the reference to the object returned by
readcsvnew (which we called
session in this example) The
mydata when calling the R function printsummary:
This illustrates the concept of function chaining. We can keep going on and keep calling new functions and pass output from previous function calls as the argument. To see a real world example of this, try the mapapp OpenCPU app.