Using external modules within AppJs and nodejs - node.js

I've built a basic demo application using AppJS/NodeJS and edge.
Heres the relevant part of the the app.js config file - Basically it just references the external modules.
.......
window.on('ready', function(){
console.log("Window Ready");
window.process = process;
window.module = module;
window.dns = require('native-dns');
window.edge = require('edge');
window.fs = require('fs');
window.frame.openDevTools();
..........
And heres the relevant javascript part of the main index.html page:
.......
function myFunction1()
{
var question = dns.Question({
name: 'www.google.com',
type: 'A'
});
var req = dns.Request({
question: question,
server: { address: '8.8.8.8', port: 53, type: 'udp' },
timeout: 1000
});
req.on('timeout', function () {
console.log('Timeout in making request');
});
req.on('message', function (err, answer) {
answer.answer.forEach(function (a) {
console.log(a.address);
});
});
req.on('end', function () {
console.log('Finished processing request');
});
req.send();
}
function myFunction2()
{
var helloWorld = edge.func('async (input) => { return ".NET Welcomes " + input.ToString(); }');
helloWorld('JavaScript', function (error, result) {
if (error) throw error;
console.log(result);
});
}
..........
If I call myFunction1() which uses another nodejs module (DNS lookup) it works perfectly. However if I call myFunction2() which uses edge I get the following error!
Uncaught TypeError: Property 'func' of object [object Object] is not a function
I've spent hours on this and for cannot work out why this happening!

Have you tried running the same myFunction2 code inside app.js i.e. in nodejs? Maybe the func function does not exist on the edge object. Check the docs maybe you need to do something like
window.edge = require('edge').Edge;
or something similar to get hold of the object that you think you have at the moment. You can also do console.log(window.edge) and see what it outputs (both in node and in browser running dev tools (F12)).
/Simon

Related

node.js TypeError: Path must be a string. Received null

I was recently working on a javascript that uses socket.io,node.js and express.js.
here is the server code.
var
port = +process.argv[2] || 8080,
sanitizer = require('validator').sanitize,
express = require('express'),
server = express.createServer(),
io = require('socket.io').listen(server),
chat = io.of('/chat'),
canvas = io.of('/canvas')
;
function sanitize(string) {
return sanitizer(string).entityDecode()
}
server.listen(port);
server.get(/(^\/.*$)/, function(request, response) {
var fileName = request.params[0];
if (fileName == '/')
fileName = '/index.html';
response.sendfile(__dirname + '/client' + fileName);
});
io.sockets.on('connection', function(socket) {
socket.on('setName', function (name) {
name = sanitize(name);
socket.set('name', name);
socket.broadcast.emit('receive', {
sender:'Server',
message:name + ' has joined.'
})
});
socket.on('send', function (message) {
socket.get('name', function(error, name) {
if (name)
socket.broadcast.emit('receive', {
sender:name,
message:sanitize(message)
})
})
});
socket.on('draw', function (command) {
io.sockets.emit('draw', command)
});
socket.on('updateCursor', function(position) {
socket.get('name', function(error, name) {
if (name)
socket.broadcast.emit('updateCursor', {
name:name,
position:position
});
});
});
socket.on('disconnect', function() {
socket.get('name', function(error, name) {
if (name) {
socket.broadcast.emit('receive', {
sender:'Server',
message:name + ' has left.'
});
socket.broadcast.emit('removeCursor', name);
}
})
});
});
I am able to set up the server successfully, but when I use the localhost on the browser, I get the following error:
TypeError: Path must be a string. Received null
at assertPath (path.js:8:11)
at win32.join (path.js:221:5)
at exports.send (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\node_modules\connect\lib\middleware\static.js:127:20)
at ServerResponse.res.sendfile (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\lib\response.js:186:3)
at C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\server.js:23:14
at callbacks (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\lib\router\index.js:272:11)
at param (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\lib\router\index.js:246:11)
at pass (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\lib\router\index.js:253:5)
at Router._dispatch (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\lib\router\index.js:280:5)
at Object.Router.middleware [as handle] (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\lib\router\index.js:45:10)
I had developed this using the unstable v0.5.8 windows binary version of node.
but I am currently running the 4.4.5 version.
Please help me, where did I go wrong?
It's a little difficult to tell from the sample code you've pasted because your stack trace references line 45 in your index.js as the source of the problem (C:\Users\Akshay\Desktop\whiteboard-master\whiteboard-master\node_modules\express\lib\router\index.js:45:10) but when I look at your sample/pasted code in an IDE, it's not doing anything there. The only call to sendfile (referenced further up in your stack trace) is earlier in the script.
Assuming that's the location of your issue, you should console.log() or otherwise debug the value of the path/filename you're attempting to send to the visitor. Note that in Windows, path delimiters are \ not /. You should use path.join() to form the final path to the file served. The ExpressJS examples illustrate this:
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});

Why does node webkit crash when downloading a big file?

Im using node webkit 0.7.5 (which is the only version so far which allows me to display video in a correct way).
I'm trying to download a big video file (200+ mb) and sometimes, not always, node webkit crashes when the file is done downloading. Writestream.end() is called, and that is when the crash happens.
My code:
var fs = require('fs');
var request = require("request");
var req = request(self.requestOptions(), function (err) {
if (err) {
//handle error
}
});
req.on("response", function (response) {
writeFile(response);
});
function writeFile(response) {
var file = fs.createWriteStream(filename);
var self = this;
response.on('data', function (data) {
file.write(data);
});
response.on('end', function () {
log.debug("response end");
file.end();//crash happens after calling this
});
response.on('error', function (err) {
//handle error, not called in this situation
});
file.on('finish', function () {
log.debug("file finish");
});
}
In general this method works excellent, but with some files and situations node webkit just decides to call it quits.
Am I doing something obviously wrong? I've searched the net for possible clues or solutions, but I haven't found anything.

SpookyJS has no Start Method while using it in Meteor

I have an weird error and can't find the cause of it for the last few hours...
I have a meteor app, that scrapes some webpages for information and everything works fine as long as I use reuqest and cheerio for static pages, but now I have a dynamic site and I wanted to use phantomjs, casperjs and spookyjs for this one, but here I get some bug...
My code is as follows, I import the npm modules at the start:
if (Meteor.isServer) {
var cheerio = Meteor.npmRequire('cheerio');
var request = Meteor.npmRequire('request');
var phantomJS = Meteor.npmRequire('phantomjs');
var spooky = Meteor.npmRequire('spooky');
And sometime later I want to use spooky to scrape some webpage:
spooky.start("https://www.coursera.org/");
spooky.then( function () {
this.fill("form", {email: user, password: pass}, true);
});`
But as soon as I call the method I get the following error message:
20150224-21:16:39.100(-5)? Exception while invoking method 'getLecturesCoursera' TypeError: Object function Spooky(options, callback) {
....
I20150224-21:16:39.281(-5)? } has no method 'start'
I20150224-21:16:39.281(-5)? at [object Object].Meteor.methods.getLecturesCoursera (app/moocis.js:72:14)
I am doing something completly wrong and I have no clue why it isn't working...
I tried to verify that spookyjs and phantomjs are installed correctly in my app, but that isn't as easy as it sounds for someone who uses them for the first time...
Like normally with spooky you have to create a new Spooky Object before you can start and run it...
if (Meteor.isServer) {
Meteor.startup( function () {
var Spooky = Meteor.npmRequire('spooky');
var spooky = new Spooky({
child: {
transport: 'http'
},
casper: {
logLevel: 'debug',
verbose: true,
ignoreSslErrors: true,
sslProtocol: 'tlsv1'
}
}, function (err) {
if (err) {
e = new Error('Failed to initialize SpookyJS');
e.details = err;
throw e;
}
spooky.start(
'https://www.google.com');
spooky.then(function () {
this.emit('hello', 'Hello, from ' + this.evaluate(function () {
return document.title;
}));
});
spooky.run();
});
spooky.on('error', function (e, stack) {
console.error(e);
if (stack) {
console.log(stack);
}
});
spooky.on('hello', function (greeting) {
console.log(greeting);
});
spooky.on('log', function (log) {
if (log.space === 'remote') {
console.log(log.message.replace(/ \- .*/, ''));
}
});
})
}

Using node-rio from Meteor Server Side Route

I'm trying to access an Rserve server using Meteor through a server side route to call R code. The Node.js module that allows access to Rserve is node-rio I have used the Async.wrap function in the meteorhacks:npm Meteor package to wrap the "evaluate" method. When I try to access the route path "/rio" in a browser, I get "1" written to the console log, which is correct for the evaluation of the command "1" in R, but Chrome hangs with the message "Waiting for localhost". It doesn't proceed to the next line and "Result: 1" is never shown. The message "net::ERR_EMPTY_RESPONSE eventually shows up in Chrome.
Router.route('/rio', function() {
var rio = Meteor.npmRequire('rio');
var evalSync = Async.wrap(rio, 'evaluate');
var result = evalSync('1');
console.log("Result: " + result);
// JSON
this.response.writeHead(200, {'Content-Type': 'application/json'});
this.response.end(result);
}, {
where: 'server'
});
"evaluate" has a callback function parameter, but it is wrapped in an options parameter and accessed:
rio.evaluate(R_COMMAND, {callback: CALLBACK_FUNCTION})
Two errors:
as you already noted rio expects the callback as a value to the callback field in the parameters, not straight in the arguments themselves.
your result ("1") wasn't actually valid JSON.
This works:
Router.route('/rio', function() {
var rio = Meteor.npmRequire('rio');
var evalSync = Async.wrap(function(exp, callback) {
rio.evaluate(exp, {callback: callback});
});
var result = evalSync('1');
console.log("Result: " + result);
// JSON
this.response.writeHead(200, {'Content-Type': 'application/json'});
this.response.end(JSON.stringify({result: result}));
}, {
where: 'server'
});
This answer will produce the expected result for 'packageVersion("base")', it uses the Node module rserve-client instead of rio to connect to Rserve. The route also handles the parameter 'pkg'. This is the StackOverflow question that pointed me in the right direction:
How to call async method from Meteor own callbacks?
Router.route('rserve', {
path: '/rserve/:pkg',
where: 'server',
action: function() {
var r = Meteor.npmRequire("rserve-client");
var Future = Meteor.npmRequire("fibers/future");
var fut = new Future();
var cmd = 'packageVersion("' + this.params.pkg + '")';
var callR = function (input) {
r.connect('127.0.0.1', 6311, function (err, client) {
client.evaluate(input, function (err, ans) {
console.log("Result: " + ans);
client.end();
fut.return(ans);
});
});
return fut.wait();
};
var result = callR(cmd);
this.response.writeHead(200, {'Content-Type': 'application/json'});
this.response.end(JSON.stringify(result));
}
});

Why might my first API call run fine, but the second one hang indefinitely?

I am trying to keep a session open with the Bloomberg Public API, relaying calls from my own service's API to it to fetch data. I am running the Node.JS / Express server locally right now. I have an API route that works fine the first time: I send the GET, and quickly get the response back. If I then send another GET to the same route, and I can see the data that the Bloomberg API returns in my server console, but it seems that the server gets stuck at the res.send(...) and I have no Idea why. I've tried numerous things like moving code blocks around and forcefully destroying variables, but to no avail. Do you guys see anything obvious that would/might work?
'use strict';
var _ = require('lodash');
var Blpapi = require('./blpapi.model');
var count = 0;
var blpapi = require('blpapi');
// Add 'authenticationOptions' key to session options if necessary.
var session = new blpapi.Session({ serverHost: '10.8.8.1', serverPort: 8194 });
var service_refdata = 1; // Unique identifier for refdata service
session.start();
session.on('SessionStarted', function(m) {
console.log(m);
session.openService('//blp/refdata', service_refdata);
});
session.on('ServiceOpened', function(m) {
console.log(m);
});
session.on('SessionStartupFailure', function(m) {
console.log('SessionStartupFailure', util.inspect(m));
session.stop();
session.destroy();
});
session.on('SessionTerminated', function(m) {
console.log('Session Terminated');
session.stop();
session.destroy();
});
exports.getStock = function (req, res) {
var stock = req.url.substring(8, req.url.length);
stock = stock.replace(/_/g, ' ');
session.on('HistoricalDataResponse', function(m) {
console.log(m);
if(m.eventType === 'RESPONSE' && m.correlations[0].value === 101) {
console.log('send');
res.send(m.data.securityData);
}
else {
res.send(500);
}
});
newRequest(stock);
};
function newRequest(sec) {
if(typeof sec !== 'string') return;
session.request('//blp/refdata', 'HistoricalDataRequest',
{ securities: [sec],
fields: ['PX_LAST', 'OPEN'],
startDate: "20140101",
endDate: "20140301",
periodicitySelection: "DAILY" }, 101);
}
function handleError(res, err) {
return res.send(500, err);
}
Edit1: If I change the res.send(m.data.securityData); to res.send(201);, the requests come back fine, so I'm figuring it has to do with that object.
I figured it out. It's because I was declaring the session.on('HistoricalDataResponse', .... statement inside of my route controller. Moving it out and adding a bit of logic around it solved the problem.

Resources