Meteor synchronous and asynchronous call to read a file - javascript

I am new to Meteor. I am using following code to read a file stored at server.
Client side
Meteor.call('parseFile', (err, res) => {
if (err) {
alert(err);
} else {
Session.set("result0",res[0]);
Session.set("result1",res[1]);
Session.set("result2",res[2]);
}
});
let longitude = Session.get("result0");
let latitude = Session.get("result1");
var buildingData = Session.get("result2");
Server Side
Meteor.methods({
'parseFile'() {
var csv = Assets.getText('buildingData.csv');
var rows = Papa.parse(csv).data;
return rows;
}
})
The problem is while I make a call it takes time to send the result back and hence wherever i am using latitude and longitude its giving undefined and page breaks. So, is there any solution to avoid this problem. One of the solution can be to make a synchronous call and wait for result to be returned.

You can make the server method run synchronously using the futures package, which should force the client to wait for the method to complete.
It might look something like this:
Meteor.methods({
'parseFile'() {
var future = new Future();
var csv = Assets.getText('buildingData.csv');
var rows = Papa.parse(csv).data;
future.return(rows);
future.wait();
}
});
This would require you installing the futures package linked above and setting up your includes properly in file containing your Meteor.methods() definitions. You might also look into good error handling inside your method.
UPDATE:
The link to the Future package is an NPM package, which you can read about here. The link above is to the atmosphere package, which looks like an old wrapper package.

Related

Is this way to access mongodb in node.js acceptable?

I am new to programming and trying to experiment a bit, still struggling with the best way to access mongoDB from within my code. I've seen a few posts here on stack overflow but they more or less all require that the code required to load mongo is included in each and every .js file. I would like to avoid that in order to keep the code for accessing my DB in only one file.
Note that I am using the "mongo-factory" module.
Would the code below be acceptable?
I've created what I would call a "producer" of database objects, database.js
var mongoFactory = require('mongo-factory');
function Database(close,callback) {
mongoFactory.getConnection(<connection string>).then(function (database) {
callback(database.db(<db name>));
if(close) database.close();
}).catch(function (err) {
console.error(err);
});
}
module.exports = Database;
Then when I want to access the database from any of my files I could do the below, avoiding to introduce db-specific parameters and the mongo-factory requirement in here:
var Database = require('./database');
var callback_actOnDatabase = function (db) {
db.collection..... do something here
};
var d = new Database(false, callback_actOnDatabase);
instead of mongo-factoy use mongoose module to connect the database,model declaration also we dont intalise the db parameters again,please go through the link
https://www.npmjs.com/package/mongoose

Firebase realtime database: writing new data is failing

I have a bunch of data that needs to be updated in my realtime database but the set command (as described here in the docs) isn't working. Here's my code, which I'm running with babel-node scriptName.js:
var config = {
//CONFIG
};
Firebase.initializeApp(config);
var dbRef = Firebase.database().ref();
getAllFirebaseDocs(dbRef);
async function getAllFirebaseDocs(dbRef, newSet) {
var snapshot = await dbRef.once('value');
var data = snapshot.val();
var bookName = "FirebaseForDummies";
var newData = {
'prop1': 'string',
'prop2': 0
}
Firebase.database().ref(bookName + "/edition/"+ 3).set(newData);
}
I'm doing some other stuff which doesn't affect the write (hence reading all existing data). I'm specifically updating/augmenting existing data, so for example; the book FirebaseForDummies has 3 editions already. This means that the editions value in the database looks something like this:
0: {data}
1: {data}
2: {data}
I want to add a fourth, so I create the db reference with FirebaseForDummmies/edition/3. Then just like in the doc, I use set and pass it the newData object. This however fails silently; I don't get any error messages, and nothing changes in the realtime database console.
edit:
I tried these commands in a babel-node session in my console, and they worked. So there's something in my script that's making the set() function not work... not sure what it is, since I have other scripts that implement set() on existing data and they all work fine.
edit2:
I added a callback as follows:
Firebase.database().ref(bookName + "/edition/"+ 3).set(newData, function(error) {
if(error) {
console.log(error);
}
else {
console.log("written!");
}
});
Again, when I try it in a babel-node console it works fine (returning 'written!') but in my script, I don't get either the error or success console.log.
The answer is not to do a process.exit() at the end of the script. I didn't even think of it because I put it there simply to close the script when it was done, but apparently it was 'cutting off' the requests. I think I should make await work with the set requests so that this can all happen synchronously.

Evented api and/or callback api in nodejs

I would like to know what is the best way to handle an evented api. My first thought is wrapping it into a callback api but I have feeling that I am blocking right here and that this is not the best approach.
Given I have a lib that returns values from a db and it is evented:
var connection = new Connection(config);
var query = new Query();
query.on('data',function(row){});
query.on('done',function(){});
This is my take ...
getAllCustomer(clb){
var connection = new Connection(config);
var query = new Query();
var results = [];
query.on('data',function(row){
results.push(row);
});
query.on('done',function(){
clb(results);
});
connection.execute(query);
connection.close();
}
I would like to use that in an hapijs or expressjs app
like to use it like this
handler: function(request,reply){
getAllCustomer(function(err,result){
reply(result);
});
}
getAllCustomers() seems to be blocking until the query is done!
So what would be the recommended way to handle that?
Is the design dessicion right to wrap the evented api in a callback api?
Or should I pass the streaming rows along with expressjs / hapijs?
So I am looking for a best practise way ... the node way...
Thanks for any help.
In the code example that you provided getAllCustomers() will be blocking, only if connection.execute(query) is blocking - and it seems the case, cause otherwise if it was asynchronous - it would have been closed by a subsequent call to connection.close() before it even had a chance to run a query.
If it isn't sync/blocking - than you need to clode sonnection in a done callback

How do I read and write files to the server with Meteor?

I'm working on a NoDB CMS in Meteor, but I'm new to both Meteor and JavaScript frameworks.
How do I go about reading and writing files to the server?
Within the Node fs module you have a writeFile function.
getUser = Meteor.users.findOne({_id : Meteor.userId()});
userObject = JSON.stringify(getUser);
var path = process.env["PWD"] + "/public/";
fs.writeFile(process.env["PWD"] + "/public/"+Meteor.userId()+'.txt', userObject,
function (err) {
if (err) throw err;
console.log('Done!');
}
);
The above snippet would create a file with all the information of the user. You could access the properties of the result of your query with something like getUser._id to prepare your data parameter (String or Buffer) to print pretty.
All this of course is server side.
you can try to use Npm.require inside the startup function. Like so
Meteor.startup(function () {
fs = Npm.require('fs');
}
But you should definitely have a look at collectionFS that does what you are looking for: storing files on the server and allowing you to retrieve them
an added advantage is that you can distribute everything over many nodes of a MongoDB cluster
to manipulate image files, you can use imagemagick with nodejs this should allow you to transform in any way you need.
The node fs module is a start. http://nodejs.org/api/fs.html
You might want to be a bit more specific with your question though, as it's kind of broad.

Can node.js execute JavaScript functions pulled from CouchDB like CouchApp does? How?

The quick overview is this: for my web app I can write most of my functionality using CouchApp and CouchDB views, etc. I love the feature of CouchApp that pushes my code up to the server via replication- this makes the deployment cycle very easy.
However, to do some arbitrary work not supported in couchdb and works around a few limitations, I need to put a web platform in front of CouchDB. I'm considering building this in node.js because it uses JavaScript and I want to continue the easy deployment method of pushing code into the database.
Here's how i imagine it working:
- I write a web server/service in node.js using the normal method and the node command to start it.
- this sevice connects to couch db and gets a virtual list and a URL mapping list. This list is stored in redis for quick lookup. This list will tell the server, when it gets a request, based on host and path, etc, which handler is to be run.
- the server fetches the handler- which is just a document, it could be a design document or an arbitrary json document in couchdb. And then executes that handler to handle the request, as if I'd writte the handler as part of node js.
So the question is, how to get a son data structure that contains a JavaScript function in it, in text form, and execute that function?
This may be blindingly obvious, but i come from a compiled background, so normally there would be a compilation step here that makes this pretty much impossible.
So, what I'm thinking is in pseudo code:
Var string thecode = getValueForMapKey(handlerFunctionIWant);
somehowmagicallyexecute(thecode)
Is there an exec or run function that will do the magical execution step above in JavaScript?
It will run in the node.js context.
You can also use it in node, like this, as a dynamic function:
var cradle = require('cradle');
var db = new(cradle.Connection)().database('db_name');
db.get('_design/node%2Fyour_code', function (err, doc) {
if (!err){
var your_code = new Function(doc['arguments'].join(','), doc.code);
your_code("cool", "also cool");
}else{
console.error('error:', err);
}
});
make your docs look like this:
{
"_id": "_design/node/your_code",
"arguments": [
"nameOfArg1",
"nameOfArg2"
],
"code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);"
}
It's in the same scope as where the new Function is called, so you have access to cradle, or you can require other libs, which will be loaded as if it was an anon function in that scope.
Put it in a design doc, then only admin can make changes, out of the box.
Here is a nicer, but similar approach:
// Format, in db:
doc = {
"_id": "_design/node",
"your_function_name": {
"arguments": [
"nameOfArg1",
"nameOfArg2"
],
"code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);"
},
"your_other_function_name": {
"arguments": [
"name"
],
"code": "console.log('hello', name, 'how\\'s it going, bro?');"
}
};
var cradle = require('cradle');
var db = new(cradle.Connection)().database('db_name');
function run_from_db(name, args){
db.get('_design/node', function (err, doc) {
if (!err){
if (doc[name] !== undefined){
var fn = new Function(doc[name]['arguments'].join(','), doc[name].code);
fn.apply(fn, args);
}else{
console.error("could not find", name, "in _design/node");
}
}else{
console.error(err);
}
});
}
run_from_db('your_other_function_name', ['konsumer']);
this will output:
hello konsumer how's it going, bro?
eval(handlerFunctionIwant) is the call to execute it. You need to make sure that there's no way for hackers to inject code into that string, of course.
It is not clear to me if this will evaluate it in a context that has access to other javescript resources, such as the rest of node.js or access to your couchdb library.

Categories

Resources