Store database attribute in var - node.js

I have the following code:
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('test.db');
db.serialize(function() {
db.run("CREATE TABLE IF NOT EXISTS counts (key TEXT, value INTEGER)");
db.run("INSERT INTO counts (key, value) VALUES (?, ?)", "counter", 0);
});
var getValue = function(res){
db.get("SELECT value FROM counts", function(err, row){
res.json({ "count" : row.value });
return;
});
};
console.log(getValue);
Output is
[Function]
But should be json. What am I doing wrong?
I took the example from http://dalelane.co.uk/blog/?p=3152
Thanks in advance :)

Of course getValue is a function, because few lines before you wrote:
var getValue = function(res){
// ...
};
so now, when you write:
console.log(getValue);
it tells you that it's a function.
What you probably want is:
getValue({json: console.log});
or maybe:
getValue({json: data => console.log(data.count)});
if you want to display that value from an object passed to res.json, if you have a db.get() function that returns one row in that format - make sure that you're using it correctly in the first place. But keep in mind that this is asynchronous so you won't be able to store it in a variable immediately.
Simplifying your example a little bit, you can do:
asyncFunc('args', function (err, data) {
if (err) {
console.log('Error:', err);
} else {
console.log('Value:', data);
}
});
but you won't be able to return that value, because returning a simple value is a synchronous process. What you can return is a promise:
function getPromise() {
return new Promise(function (resolve, reject) {
asyncFunc('args', function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
that you can then use like this:
getPromise()
.then(value => console.log('Value:', value))
.catch(error => console.log('Error:', error));
If you don't know why is that then you can see some other answers where I explain how to get data from asynchronous function calls which you may find helpful:
A detailed explanation on how to use callbacks and promises
Explanation on how to use promises in complex request handlers
An explanation of what a promise really is, on the example of AJAX requests
An explanation on how to handle errors in callbacks and promises

You did not call the getValue function. Call it like this: getValue(). But that function returns null.
You will need to start with a more basic example. First learn about function calls, then when you have that down move on to other things.

Related

Node Functions Return Nothing sqlite3

I'm trying to use sqlite3 in a project and I'm running into a problem. My functions aren't returning any values. I added a console.log before the return statement and oddly enough, it works, but logs after the function has returned.
console.log(getNext());
function establishConnection(callback) {
const db = new sqlite3.Database('database.db');
db.serialize(() => {
callback(db);
});
db.close();
}
function getNext() {
establishConnection(db => {
db.get('SELECT col1, col2 FROM table ORDER BY priority LIMIT 1;', (err, row) => {
console.log([row.col1, row.col2]); // works
return [row.col1, row.col2]; // doesn't work
});
});
}
I'm no expert at Node but this seems like something that should work and I don't understand why it doesn't. Could someone please explain this to me and possibly provide a solution?
getNext is asynchronous, this is why you see logging after the function "returns". Your code currently uses callback style so this answer will follow your format. Using promises or async/await is a more modern approach.
getNext(result => console.log(result));
function establishConnection(callback) {
const db = new sqlite3.Database('database.db');
db.serialize(() => {
callback(db);
});
db.close();
}
function getNext(callback) {
establishConnection(db => {
db.get('SELECT col1, col2 FROM table ORDER BY priority LIMIT 1;', (err, row) => {
callback([row.col1, row.col2]);
});
});
}

Creating functions to chain promises correctly

I am trying to get Promise chaining working for me correctly.
I believe the problem boils down to understanding the difference between:
promise.then(foo).then(bar);
and:
promise.then(foo.then(bar));
In this situation I am writing both foo and bar and am trying to get the signatures right. bar does take a return value that is produced by foo.
I have the latter working, but my question is what do I need to do to get the former working?
Related to the above is the full code (below). I don't have the different logs printed in the order I am expecting (expecting log1, log2, log3, log4, log5, but getting log3, log4, log5, log1, log2). I am hoping as I figure the above I will get this working right as well.
var Promise = require('bluebird');
function listPages(queryUrl) {
var promise = Promise.resolve();
promise = promise
.then(parseFeed(queryUrl)
.then(function (items) {
items.forEach(function (item) {
promise = promise.then(processItem(transform(item)))
.then(function() { console.log('log1');})
.then(function() { console.log('log2');});
});
}).then(function() {console.log('log3')})
).then(function() {console.log('log4')})
.catch(function (error) {
console.log('error: ', error, error.stack);
});
return promise.then(function() {console.log('log5');});
};
What is the difference between promise.then(foo).then(bar); and promise.then(foo.then(bar));?
The second one is simply wrong. The then method takes a callback as its argument, not a promise. That callback might return a promise, so the first one is equivalent to
promise.then(function(x) { return foo(x).then(bar) })
(assuming that foo returns a promise as well).
Your whole code appears to be messed up a bit. It should probably read
function listPages(queryUrl) {
return parseFeed(queryUrl)
.then(function (items) {
var promise = Promise.resolve();
items.forEach(function (item) {
promise = promise.then(function() {
console.log('log1');
return processItem(transform(item));
}).then(function() {
console.log('log2');
});
});
return promise;
}).then(function() {
console.log('log3')
}, function (error) {
console.log('error: ', error, error.stack);
});
}

Way to use mongodb's find cursor's next/each functions as a promise after promisifying mongodb with Bluebird

The node mongodb docs specify to use next/each for large number of documents so as to not have everything loaded onto memory if we were to use toArray.
So, i thought my sample code should work as is. But it just returns one document.
What should be the correct way to deal with this problem?
This is my code sample :
var findAsync = function (collection,query) {
return mongodb.MongoClient.connectAsync(mongodbServerString)
.then(function (db) {
return [db.collection(collection).find(query), db];
});
};
findAsync("UserProfile",{})
.spread(function (cursor,db) {
return [cursor.project({Email:true}),db];
})
.spread(function (cursor, db) {
return cursor.eachAsync().then(function (doc) {
console.log(doc);
}).catch(function () {
db.close();
});
});
Promises represent singular values. Promises are basically like function returns, since a function cannot return multiple values - it wouldn't make sense to convert each to a promise returning function.
What you can do is either convert it to an Observable returning function and then use .forEach on that to get a promise back for the completion of the sequence or you can implement something similar manually:
function each(cursor, fn) {
return new Promise((resolve, reject) => {
cursor.forEach((err, data) => {
if(err) {
cursor.close();
return reject(err);
}
try { fn(data); } catch(e) { cursor.close(); reject(e); }
}, err => { { // finished callback
if(err) reject(err);
else resolve();
});
});
}
Which would let you write:
each(cursor, doc => console.log(doc)).then(...).catch(...)
Also note that Mongo connections are persistent, you're supposed to connect once when the server starts and then keep the connection open for as long as the server is run.

NodeJs Mongoose How can I get out a data from "find().then" in a "find().then"?

Sorry for my Title, I don't know what can I put.
Can you help me please, I would like to print data from a "then" in a "then" ?
Thank you
models.book.find()
.then( function (content) {
var i = 0;
while (content[i]) {
models.author.findOne({"_id": content[i].author_id}, function(err, data) {
console.log(data); //here, it' good
content[i] = data;
MY_DATA = content;
return MY_DATA;
});
i++;
};
})
.then(function (result) {
console.log(result); // here I would like to print MY_DATA
});
There are a number of problems with your code, and I don't think it's behaving as you're expecting it to.
Chaining Promises
In order to effectively chain promises how you're expecting, each promise callback needs to return another promise. Here's an example with yours changed around a bit.
var promise = models.book.find().exec(); // This returns a promise
// Let's hook into the promise returned from
var promise2 = promise.then( function (books) {
// Let's only get the author for the first book for simplicity sake
return models.author.findOne({ "_id": books[0].author_id }).exec();
});
promise2.then( function (author) {
// Do something with the author
});
In your example, you're not returning anything with your callback (return MY_DATA is returning within the models.author.findOne callback, so nothing happens), so it's not behaving as you're expecting it to.
model.author.findOne is asynchronous
model.author.findOne is asynchronous, so you can't expect to call it multiple times in the callback without handling them asynchronously.
// This code will return an empty array
models.book.find( function (err, books) {
var i = 0, results = [];
while (books[i]) {
models.author.findOne({ "_id": books[i].author_id}, function (err, data) {
// This will get called long after results is returned
results.push(data);
});
i++;
};
return results; // Returns an empty array
});
Handling multiple promises
Mongoose uses mpromise, and I don't see a method to handle multiple promises together, but here's a way your case could be done.
var Promise = require('mpromise');
models.book.find().exec()
.then( function (books) {
var i = 0,
count = 0,
promise = new Promise(),
results = [];
while (books[i]) {
models.author.findOne({ "_id": books[i].author_id }, function (err, author) {
results.push(author);
count++;
// Keep doing this until you get to the last one
if (count === books.length) {
// Fulfill the promise to get to the next then
return promise.fulfill(results);
}
return;
});
}
return promise;
})
.then( function (results) {
// Do something with results
});
I don't know if this will work exactly like it is, but it should give you an idea of what needs to be done.

Loop data with Node.js

I am having my code as
function updateData(data){
data.forEach(function(obj){
users.find({_id:obj.userId}).toArray(
function(e, res) {
obj.userData = res;
console.log(res)
});
});
return data;
}
The problem is I am unable to find the updated data, I am trying to update my data and adding one more field to it based on userId. The data parameter is an array containing the output from comments table. hope you understand the scenario.
It looks that users.find({...}).toArray(function(...){...}) is going to be asynchronous, so there is no way that you can be sure that the db call has been completed and that each data.obj has been updated before data is returned.
Instead of using the javascript Array.prototype.forEach() function, you could use the NodeJS async.each function from the async library by Caolan which would iterate through the array, update each object and then return the data object only when all functions calls have completed.
For example:
var async = require("async");
function updateData(data){
async.each(data, function(obj, callback) {
users.find({_id:obj.userId}).toArray(
function(e, res) {
obj.userData = res;
callback(e);
}
);
},
function(error){
return data;
}
}

Resources