joshkatz / r-script

A simple little module for passing data from NodeJS to R (and back again).

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Special Considerations for Windows Machines

johnlin89 opened this issue · comments

I personally have a Mac and was using the latest distribution of R at the time of writing (Version 3.5.1). When testing my R code and NodeJS code on a Windows machine for another user, I ran into a couple errors. Hopefully, the below is enlightening for others.

  1. Adding R to PATH

I kept getting this error

events.js:183
     throw er; // Unhandled 'error' event
     ^

Error: spawn Rscript ENOENT
   at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
   at onErrorNT (internal/child_process.js:362:16)
   at _combinedTickCallback (internal/process/next_tick.js:139:11)
   at process._tickCallback (internal/process/next_tick.js:181:9)

I believe NodeJS cannot call R through command prompt.
In order to resolve, you need to add R to PATH for Windows machines.

See http://yizhexu.com/2017/02/r-path/ with excerpt below

1. Verify R is installed in the following path: C:\Program Files\R\R-3.3.2\bin\x86
2. Open the start menu and type in “View advanced system settings”, click on “Environment variables”
3. Under “System variables”, select Path and click on edit.
4. Click “New”, and add the folder address for R to there (C:\Program Files\R\R-3.3.2\bin\x86)
5. Open windows power shell and type in Rterm or R.exe to launch R command line tool

After adding R to PATH, you need to completely restart NodeJS.

  1. Security Issues

You may run into issues with R when updating packages/installing packages because of Windows Security. Make sure that you have granted full control of the R files for your user account.

https://winaero.com/blog/how-to-take-ownership-and-get-full-access-to-files-and-folders-in-windows-10/

https://stackoverflow.com/questions/5059692/unable-to-update-r-packages-in-default-library-on-windows-7

I believe the location is something like C:/Program Files/R/R-3.2.1/library, but I've honestly forgotten at this point. I think there was another location on the Windows machine that I had to change the permissions to allow R to download whatever packages were needed.

  1. Synchronous vs Asynchronous Calls

I kept running into this error

These are the inputs: 2018-01-01, 2019-01-01, E, 2, 8
undefined:1
installing packages:njsonlite
^

SyntaxError: Unexpected token i in JSON at position 0
   at JSON.parse (<anonymous>)
   at Socket.<anonymous> (C:\Users\HP\Desktop\project_mss\mss-server\node_modules\r-script\index.js:35:25)
   at emitOne (events.js:116:13)
   at Socket.emit (events.js:211:7)
   at addChunk (_stream_readable.js:263:12)
   at readableAddChunk (_stream_readable.js:250:11)
   at Socket.Readable.push (_stream_readable.js:208:10)
   at Pipe.onread (net.js:601:20)

If you look at the index.js and launch.R code within the r-script package, it is pretty revealing.

From launch.R we have

source(file.path(Sys.getenv("DIRNAME"), "needs.R"))
needs(jsonlite)

It seemed to me that the last output of R is what tries to get converted to JSON format to pass to NodeJS. However, I couldn't understand why installing packages:njsonlite was the last output (as it was from launch.R which I believe just calls the specific R script you need).

I experimented a LOT over 2 or 3 days and ended up changing to synchronous calls previously from asynchronous calls.

Within my code we changed from

         var plotType = "scatter";
         var fpmScatter = R(fpmMortalityPath)
             .data(req.query.startDate,req.query.endDate,req.query.formType,req.query.userLevel,req.query.userId,plotType)
             .call(function(err, a) {
                 if (err) throw err;
                 res.json(a)
             });
         }

to

        var plotType = "scatter";
        var data = R(fpmMortalityPath)
            .data(req.query.startDate,req.query.endDate,req.query.formType,req.query.userLevel,req.query.userId,plotType)
            .callSync();
                console.log(data);
            res.json(data);
        }

After making this change, the code worked. I am still not sure why this was the case. I speculated that there might be differences between calls between Windows and Mac machines? However, I am not too sure of this theory.