How do you avoid asynchronous call in this case I have tried everything each time the res.render is too early and is missing objects from state. playingCollection is a mongodb collection.
var state = [];
playingCollection.find({},function(err, companies) {
companies.each(function(err,company){
if (company !== null) {
var obj = company.playername;
state.push(obj);
}
res.render('index', { title: 'Demo', error: req.query.error, players: state, head: 'Currently playing:'});
state = [];
return;
});
});
Here is one approach to handle this using toArray after the call to find():
playingCollection.find({}).toArray(function(err, companies) {
if(err) {
res.render('error', {whatever});
return;
}
var state = [];
var i;
for(i=0; i<companies.length; i++) {
state.push(companies[i].playername);
}
res.render('index', { title: 'Demo', error: req.query.error, players: state, head: 'Currently playing:'});
});
Below is a simple way using the Cursor object returned from find. It relies only on the fact that the each call will pass a null when the list is exhausted.
var state = [];
playingCollection.find({}).each(function(err, company) {
if (company !== null) {
state.push(company.playername);
} else {
res.render('index', { title: 'Demo', error: req.query.error, players: state,
head: 'Currently playing:'});
return;
}
});
If you knew you were only interested in one field from the collection, you should also limit the results using the optional projection parameter:
playingCollection.find({}, { playername: 1 }).each(....);
In the above, it would return only the playername and _id field for each document.
Related
I'm new to Js, and would appreciate some help.
Currently, via tedious js, I've written a sql function that passes an insert statement that loops through an array of objects and inserts each property in each object in array to SQL.
To do this, I've written a loop to iterate through the array, and insert each property as a new entry into sql.
However, when i try to execute the function after the connect, the function returns error Request is not a constructor
Here is the full code below. Is there some scope issue here, or am I not correctly handling the tedious js events properly or is there some sort of issue with my for loop?
var jsonArray = [];
let jsonobj = {
test: "1",
test2: "2"
}
let jsonobj1 = {
test: "23",
test2: "54"
}
jsonArray.push(jsonobj)
jsonArray.push(jsonobj1)
jsonArray.push(jsonobj)
var config = {
server: '123', //update me
authentication: {
type: 'default',
options: {
userName: '123', //update me
password: '1234' //update me
}
},
options: {
// If you are on Microsoft Azure, you need encryption:
//encrypt: true,
requestTimeout: 30 * 1000,
trustServerCertificate: true,
database: 'db', //update me
rowCollectionOnRequestCompletion: true,
rowCollectionOnDone: true
}
};
var connection = new Connection(config);
connection.on('debug', function(err) { console.log('debug:', err);})
connection.on('connect', function(err) {
});
for (var i = 0; i < jsonArray.length; i++){
var sql = `insert into store (storekey,ip,port) values ( \'${jsonArray[i].test2}\' , '2' , '6');`
executeStatement1(sql)
}
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
function executeStatement1(sql) {
request = new Request(sql, function(err) {
if (err) {
console.log(err);}
});
request.on('row', function(columns) {
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log(" success " + column.value);
}
});
});
connection.execSql(request);
}
I think this is different than the many other questions which are concerned with this and bind. Notably How to access the correct `this` context inside a callback?
I have a method on an object that uses that objects properties, and makes an ajax call. I want that value then stored in a new property object. I'm just not sure how to assign the callback function to the property.
Constructor:
function congressMember(state, district) {
this.state = state
this.district = district
}
Method on the prototype:
congressMember.prototype.getMember =
function() {
govTrack.findRole({ current: true, state: this.state, district: this.district }, function(err, res) {
if (!err) {
return res.objects[0].person // this won't work
}
})
}
And then I want to make a new instance: var myHouseRep = new congressMember('WY', 1); The issue isn't with this but instead getting the value "out of" the callback.
Trying to keep the process transparent, here is a second stab:
function foo(state, district, fn) {
govTrack.findRole({ current: true, state: state, district: district }, function(err, res) {
if (!err) {
fn(res.objects[0].person)
} else {
console.log('error')
}
})
}
congressMember.prototype.getDetails =
function() {
_this = this
foo(this.state, this.district, function(cb) {
_this.details = cb
})
}
You can define a variable as undefined, then assign a value.
var foo;
function bar(baz) {
this.baz = baz;
foo = this.baz;
}
bar(42)
console.log(foo) // 42
My second stab at the problem actually solves the issue, I was confused because I was console.oging after the call to the method.
function foo(state, district, fn) {
govTrack.findRole({ current: true, state: state, district: district }, function(err, res) {
if (!err) {
fn(res.objects[0].person)
} else {
console.log('error')
}
})
}
congressMember.prototype.getDetails =
function() {
_this = this
foo(this.state, this.district, function(cb) {
_this.details = cb
console.log(_this) // The object now has the returned value
// as a property.
})
}
I have tasks defined as array of objects. getHbaseAllCountries returns all the country codes as an array which I’m trying to store in the variable selectedCountries. I pass this var selectedCountries [] to getComponentsGraphData to get the data. But when I console.log(selectedCountries) it gives me empty array [] though I have added a callback.
var tasks = [{
func: 'getHbaseAllCountries',
options: options
}];
var results = [];
var selectedCountries= [];
async.forEach(tasks, function(value, callback) {
if(value["func"] === 'getHbaseAllCountries') {
cmodel.getHbaseAllCountries( value["options"],function(err, values) {
if (err) {
v.send(err);
return;
}
for(var index=0; index< values.length; index++){
selectedCountries.push(values[index].key);
}
console.log(selectedCountries);// prints the desired results
callback(err,values);
});
}
console.log(selectedCountries);// prints []
cmodel.getComponentsGraphData(type, selectedCountries, value["country"], value["model"], function(err, data) {
//console.log("Data for: " + JSON.stringify(value));
results.push({
_id: value["key"],
data: data
});
callback(err, data);
});
}, function(err) {
if (err) {
v.send(err);
return;
}
v.send(results);
});
You call getComponentsGraphData but you don't know if your request getHbaseAllCountries as ended. You should move your call of getComponentsGraphData as suggested in the comments. Also, the use of chained promises would be better.
if(value["func"] === 'getHbaseAllCountries') {
cmodel.getHbaseAllCountries( value["options"],function(err, values) {
[...]
cmodel.getComponentsGraphData....
}
}else{
cmodel.getComponentsGraphData....
}
Help:
I'm an object of Firebase and can not recover only one item from the list because the key is a objectId and the doc api JS Firebase, it does not have a method to recover for me.
Can you help me?
Controller
var rooms = Rooms.all();
console.log('All Rooms:', rooms);
console.log('Rooms length:', rooms.length);
// New test room
if (!rooms) {
var objRooms = [
{
cc: 'Business 1',
name: 'Chat 1',
city: 'Curitiba',
state: 'PR'
},
{
cc: 'Business 2',
name: 'Chat 2',
city: 'Floripa',
state: 'SC'
}
]
var objRoom = Rooms.save(objRooms);
console.log('ROOMID: ', objRoom.key());
}
Service
.factory('Rooms', function ($firebaseObject) {
// Might use a resource here that returns a JSON array
var ref = new Firebase(firebaseUrl);
var rooms = $firebaseObject(ref.child('rooms'));
return {
all: function () {
return rooms;
},
get: function (roomId) {
// Simple index lookup
console.log('ROOMD:', rooms);
return rooms[ ref.child(roomId) ];
},
save: function (roomData) {
var obj = ref.child('rooms');
var onComplete = function (error) {
if (error) {
console.log('Data could not be saved: ', error);
}
else {
console.log('Data saved successfully!');
}
};
return obj.push(roomData, onComplete);
}
}
})
Output:
Chat Controller initialized!
controllers.js:117 Object {params: Object, current: Object, $current: extend, transition: null}$current: extendcurrent: Objectget: (stateOrName, context)go: go(to, params, options)href: href(stateOrName, params, options)includes: includes(stateOrName, params, options)is: is(stateOrName, params, options)params: ObjectroomId: "-JxlCvzgbdkQfoA1Of78"__proto__: Objectreload: reload()transition: nulltransitionTo: transitionTo(to, toParams, options)__proto__: Object
services.js:78 Selecting the room with id: -JxlCvzgbdkQfoA1Of78
services.js:20 ROOMD: d {$$conf: Object, $id: "rooms", $priority: null}
app.js:43 Logged in as : simplelogin:2
The factory Rooms is a problem:
get: function (roomId) {
// Simple index lookup
console.log('ROOMS:', rooms);
console.log('ROOM specified:', ref.child(roomId).key());
return rooms[ ref.child(roomId) ];
},
[Update]
I created the factory Objects for filter Object data:
.factory('Objects', function () {
return {
filter: function (objectValues, objectKey) {
// to take an action after the data loads, use the $loaded() promise
objectValues.$loaded().then(function () {
// To iterate the key/value pairs of the object, use angular.forEach()
angular.forEach(objectValues, function (value, key) {
if (key === objectKey) {
console.log(objectValues[objectKey]);
return objectValues[objectKey];
}
});
});
}
}
})
and Rooms factory, I edited method get and set:
get: function (roomId) {
return Objects.filter(rooms, roomId);
},
[Update]
I have a database based in the image:
I need list object data.
JavaScript Api
https://www.firebase.com/docs/web/api/
First of all you should use Angularfire which provides some useful methods for using Firebase with AngularJS. You can find the documentation here:
https://www.firebase.com/docs/web/libraries/angular/api.html
Now, your question is how to access an single item using it's key. You can do that simply by just providing the url to that object when retrieving either a $firebaseArray or $firebaseObject (when using Angularfire API):
http://myfirebase.firebase.io/blazing-heat-9118/rooms/ + roomId
And then pass this url to a new Firebase() call:
var ref = new Firebase('http://myfirebase.firebase.io/blazing-heat-9118/rooms/' + roomId);
var room = $firebaseObject(ref);
// To take an action after the data has finished loading, use the $loaded() promise
obj.$loaded().then(function(res) {
console.log(res); // res will be the room object
// To iterate the key/value pairs of the object, use angular.forEach()
angular.forEach(obj, function(value, key) {
console.log(key, value);
});
});
Now you will have fetched the single room from the database.
I'd suggest reading through the Angularfire documentation thoroughly as it contains some great methods for handling your data.
I receive a POST argument that looks like this:
sort:
[
{ field: 'name', dir: 'asc', compare: '' },
{ field: 'org', dir: 'asc', compare: '' }
]
}
and I need to create a MongoDB query based on that, so it should look like:
db.collection("my_collection").find( ... ).sort({'name': 'asc', 'org': 'asc'}).toArray(...);
Anyways, keep in mind that more fields could be passed. Also, it could happen that none of those fields is passed, meaning that the query won't have .sort().
My question: How can I create dynamically a query with Node's MongoDB driver? Is there a query builder or something similar?
I've found that most cases are unique regarding passed data, so building query objects varies from project to project.
So first ideas was to create middleware for express (in my case), that would parse query arguments into objects that are valid for query.
mongo-native can use as chained options to cursor, as well as in object:
Chained:
items.find({ type: 'location' }).sort({ title: 1 }).limit(42).toArray(function(err, data) {
// ...
});
Non-chained:
items.find({ type: 'location' }, { sort: { title: 1 }, limit: 42 }).toArray(function(err, data) {
// ...
});
As you can see Non-Chained can accept everything as object, while chained returns cursor after every method and can be reused. So generally you have two options:
For Chained:
var cursor = items.find({ type: 'location' });
if (sort) {
cursor.sort(sort);
}
cursor.toArray(function(err, data) {
// ...
});
For Non-Chained:
var options = { };
if (sort) {
options.sort = sort;
}
items.find({ type: 'location' }, options).toArray(function(err, data) {
// ...
});
It is important to remember that any data from query have to be validated and parsed properly. As well if you are developing API (for example), and will decide to change the way sorting arguments are passed or will want to add new way, then making middleware (in express.js) for parsing this data - is the way to go.
Example for pagination:
function pagination(options) {
return function(req, res, next) {
var limit = options.limit ? options.limit : 0;
var skip = 0;
if (req.query.limit) {
var tmp = parseInt(req.query.limit);
if (tmp != NaN) {
limit = tmp;
}
}
if (req.query.skip) {
var tmp = parseInt(req.query.skip);
if (tmp != NaN && tmp > 0) {
skip = tmp;
}
}
if (options.max) {
limit = Math.min(limit, options.max);
}
if (options.min) {
limit = Math.max(limit, options.min);
}
req.pagination = {
limit: limit,
skip: skip
};
next();
}
}
Usage:
app.get('/items', pagination({
limit: 8, // by default will return up to 8 items
min: 1, // minimum 1
max: 64 // maximum 64
}), function(req, res, next) {
var options = {
limit: req.pagination.limit,
skip: req.pagination.limit
};
items.find({ }, options).toArray(function(err, data) {
if (!err) {
res.json(data);
} else {
next(err);
}
});
});
And url examples:
http://example.com/items
http://example.com/items?skip=64
http://example.com/items?skip=256&limit=32
So it is the way to develop well flexible framework, which does not creates any rules of how things have to be coded as well as solving your challenge.