Search code examples
javascriptrasynchronousopencpu

OpenCPU and asynchronous programming with JavaScript


I try to get some data from a MySQL database into my JavaScript-WebApp via OpenCPU. Somehow I can't solve the following problem:

My JavaScript function looks something like this:

var array; //contains IDs already
function getStuffFromDb(){
  for(var i in array){
    var query = "SELECT value FROM table WHERE id=" + array[i].id + ";";
    ocpu.call("queryDb",{
      query : query
    }, function(session){
      session.getObject(function(data){
        array[i].data = data;
      });
    });
  }
}

I'm calling the R function "queryDb" here for every ID in the array. The problem is that this only works if the array is of length 1, which seems to be right as ocpu.call works asynchronously. So I can think of two solutions for this here, but wasn't able to get anything working yet.

Idea 1: Pass another parameter to the R function that contains the current array index. Then let the R function return that index back again so that I can insert the data in the right place of the array. This should look somewhat like that:

...
query : query,
index : i
...
session.getObject("index", function(index){
...

Idea 2: I think there has to be a more convenient way without passing the index around, but unfortunately I have no idea how to implement it. I tried to use ocpu.rpc since I thought it was synchronous but the results were the same.

In the end idea 2 seems like the better choice to me but I have no clue how to do it. The problem with idea 1 is that I can't find any examples on how to access any values besides the return value of the called R function. Wouldn't I call a variable that was set inside the called R function by passing its name with the session.getObject-method like I wrote above? Everything I get back is "Object 'index' not found in call:get(reqobject, envir = sessionenv, inherits = FALSE)".

I'd really appreciate some help here, since I'm lost in all this asynchronous and R stuff. So thanks in advance for any answers!


Solution

  • Idea 2 sounds not too bad... You probably will have to get rid of the loop and get the data one after the other. Call the the next asynchronous action only, when the last one is finished!