Tile38 Near by query node call back function is not working - node.js

I'm building a small GEO application and it's using http://tile38.com/ and https://www.npmjs.com/package/tile38 node module. Everything working fine but I'm unable to get result from the NEARBY query from the node module. It looks like the call back function isn't working, I've spent lot of time but couldn't find a way out. What I want is get the result from the nearby query and assign to a variable.
Here is the code:
var Tile38 = require('tile38');
var client = new Tile38({host: 'localhost', port: 9851, debug: true });
// set a simple lat/lng coordinate
client.set('fleet', 'truck1', [33.5123, -112.2693])
// set with additional fields
client.nearbyQuery('fleet').distance().point(33.5123, -112.2693, 6000).execute((err, results) => {
console.log("########");
// this callback will be called multiple times
if (err) {
console.error("something went wrong! " + err);
} else {
console.log(results + "##########");
}
});;
but when I try the following simple query it's working fine.
client.get('fleet', 'truck1').then(data => {
console.log(data); // prints coordinates in geoJSON format
}).catch(err => {
console.log(err); // id not found
});
ALSO when I try the RAW query in the tile38-cli it's working fine.
NEARBY fleet POINT 33.5123 -112.2693 6000
Any help would appreciated.
Thanks in advance.
EDIT
I tried the following also but didn't work.
let query = client.nearbyQuery('fleet').distance().point(33.5123, -112.2693, 6000)
query.execute(function(results).then(results => {
console.dir(results); // results is an object.
}))
Receiving following error
query.execute(function(results).then(results => {
^
SyntaxError: Unexpected token .

the author of the node library for Tile38 here. Sorry for the trouble getting this working. I noticed a typo in the readme which may have thrown you off. I will correct this.
The execute() method returns a Promise, and (as you already figured out) the example should have stated
query.execute().then(results => {
console.dir(results);
});
instead of
query.execute(function(results).then(results => {
console.dir(results);
});

After long time debugging I found that following code is working:
let query = client.nearbyQuery('fleet').distance().point(33.5123, -112.2693, 6000)
query.execute().then(data => {
console.dir(results); // results is an object.
}))

Related

Async await result

Currently in a professional transition, I'm working on a study project where I have to create a kind of mini forum. I used node.js/express and sequelize for my database.
In the code bellow, my API try to retrieve 10 last messages (with pagination stuff) to send to my welcome page. It perfectly works. The problem is that some messages have a null title because they are just answers of other messages. I'd like to change this null title by the parent_id_msg title I saved into db.
But because of async code, I receive promise object and I can't use it into my synchronous code (resulting of an undefined title at the end). After reading many ressources and trying some solutions for the last 3 days, I thinks I understand the problem about async/await used with sync code, but I still don't understand how to override it and progress.
PS : I'm not sure of my "async list" but I don't know where to put async :(
exports.lastsMessages = (req, res, next) => {
//find 10 last messages (responses includes)
let answer = {
count : 0,
list:[]
};
let tmp;
Message.findAndCountAll({
order:[['creation_date', 'DESC']],
offset: 10 * req.body.pageNbr - 10,
limit: 10
})
.then( async list=>{
answer.count = list.count;
for(let i = 0; i<list.rows.length;i++){
tmp = list.rows[i].dataValues;
if(tmp.title === null || tmp.title === ""){
console.log('before'+ tmp.title) // output NULL as expected
tmp.title = await findTitle(tmp.parent_msg_id);
console.log('after '+ tmp.title)// output undefined, not as expected :(
}
answer.list.push(tmp)
};
res.status(200).json({...answer, message:'10 derniers messages'})
})
.catch(error => res.status(400).json({error, message:'Messages non récupérés'}));
};
async function findTitle(parentId){
Message.findOne(
{attributes:['title'],
where:{id:parentId}})
.then(potatoes=> {
console.log('inside '+ potatoes.dataValues.title)
//output parent message title inside function, as excepted
return potatoes.dataValues.title});
};
Thank you in advance (and sorry as beginner for potential mistakes, misunderstanding and english level)
You are not returning anything from findTitle.
Try this on the first line of the findTitle function:
return Message.findOne(...
Also the findTitle function does not need to be async because you are not using await inside it. As another aside, it's generally a bad idea to use await inside loops.

res.render() calls promise twice expressjs

Hello I am still a beginner in Nodejs and MongoDB. When I am running res.render() function as shown below I get 2 console logs, first with the correct result from mongodb find query and second with null. If I remove res.render() It works properly with only one console.log() output and not the second null.
router.get('/:areaslug', (req, res) => {
// Query results
let areavar = {}
return client.db("AwesomeApartments")
.collection("areas")
.findOne({slug: req.params.areaslug
})
.then((datadb) => {
// first time shows correct results next it shows null
console.log(" bug-testing : "+JSON.stringify(datadb));
//storing result of first query to my object
areavar = datadb;
return client.db("AwesomeApartments")
.collection("apartments")
.find({area:datadb._id})
.toArray()
})
.then((apartmentdb) => {
// Storing results of second query
areavar.apartments = apartmentdb;
//removing this solves the issue
return res.render('area',areavar);
}).catch(err =>
{
console.log(err);
return;
})
});
To those who find their way here, browser was generating two get requests. First one for query and second one for favicon.ico. Handling favicon.ico request solved this issue.

"array.forEach is not a fuction" after firebase deploy but works on firebase serve

After deployment my array does not seem to be defined and I get a "forEach is not a function" error:
textPayload: "TypeError: currencies.forEach is not a function
at currenciesMenuConfiguration (/srv/menu/currencies-menu.js:22:16)
Here's the code for the currencies array:
async function currenciesMenuConfiguration() {
currencies = await getCol("currencies")
currencies.forEach(element => {
return currenciesList[element[Object.keys(element)].id] = element[Object.keys(element)].current
});
}
This gets called right after being defined with currenciesMenuConfiguration()
getCol is defined as:
// Get all documents in collection from Firestore
async function getCol(colName) {
return fs.collection(colName).get()
.then(res => {
return res.docs.map(doc => {
var rObj = {};
rObj[doc.id] = doc.data();
return rObj;
})
})
.catch(err => {
return `Error getting collection: ${err}`;
});
}
As mentioned on firebase serve locally this works without an issue. After deployment, I get this error. Am I missing something about asynchronous code in the cloud?
Also, any tips on how I would go about debugging this myself would be much appreciated. #BeginngersLife.
// I have checked the questions on so about firebase serve vs deployment but they mostly deal with issues around deployment or don't address the issue I am facing. One question that might help me get further in this is: firebase serve and debugging functions?.
See comment below question: I did indeed not return an array but an object. Closing. Thanks for the hint #Frank van Puffelen.

Error when using moment.max with the results of a mongoDB query

I am working on a nodeJS application that inserts documents into a mongoDB collection. The document has a createdAt field that records the time of creation. I also have a function that logs the most recent match of a query to the console.
Code:
function getResult(player){
let timeList = [];
MongoClient.connect(url, (err, db) => {
if(err){
console.log(err);
}
else{
let count = db.collection('PokeBook').count({ 'player1': player }); //count function returns a promise
count.then((val) => {
db.collection('PokeBook').find({ 'player1': player }).forEach((doc) => {
timeList.push(doc.createdAt);
console.log(doc.createdAt);
if(val===timeList.length){
myEmitter.emit('full', timeList);
}
});
});
}
});
}
//code for the emitter:
myEmitter.on('full', (arr) => {
console.log('full emitted');
console.log(moment.max(arr));
});
the code returns an error saying moments[i].isValid is not a function. Commenting the moment.max line of code results in successfully logging "full emitted" to the console.
Any advice on why this happens and how to fix this will be much appreciated. :)
moment.max() expects an array of Moment objects, but doc.createdAt is (probably) a regular Date object. You can try to replace:
timeList.push(doc.createdAt);
with:
timeList.push(moment(doc.createdAt));
so arr would be an array of Moment objects.
Alternatively, you can implement max yourself w/o using moment, assuming doc.createdAt is either Date or Number:
console.log(arr.sort()[arr.length-1]);

Returning response from Mongoose promise

Followup from this question > Stopping response if document isn't found since it was recommended I use Promise.
So basic premise, I want node to return "Can't find ID" message if we can't find the id in our database.
v1.post("/", function(req, res) {
// If the project_id isn't provided, return with an error.
if ( !("project_id" in req.body) ) {
return res.send("You need to provide Project ID");
}
// Check if the Project ID is in the file.
helper.documentExists( ProjectsData, {project_id: req.body.project_id} )
.then(function(c) {
if ( c == 0 ) {
return res.send("The provided Project Id does not exist in our database.");
} else {
var gameDataObj = req.body;
GameData.addGameId(gameDataObj, function (err, doc) {
if (err) {
if (err.name == "ValidationError") {
return res.send("Please send all the required details.");
}
throw err;
};
res.json(doc);
})
};
});
});
And helper.documentExists
module.exports = {
documentExists: function(collection, query) {
return collection.count( query ).exec();
},
};
But the script continues to run after this and prints the "required data not found".
Output:
required data not found
1
I am using native ES6 Promises.
var mongoose = require("mongoose");
mongoose.Promise = global.Promise;
EDIT: Included the entire get route. (will fix those throw err later)
#######POINT 1#########
ProjectsData.count( {project_id: req.body.project_id} )
.then(function(c) {
#######POINT 3#########
if ( c == 0 ) {
console.log("1");
return res.send("The provided Project Id does not exist in our database.");
console.log("2");
}
});
#######POINT 2#########
//some other logic
console.log("required data not found");
Following async workflow: after POINT 1, the promise is created and your handler is attached. Now POINT 2 will continue, while (at some future clock the promise is resolved and you reach POINT 3.
With my limited understanding of your workflow/purpose I'd say simply put POINT 2 code in the else{} of the if at POINT 3 (as you rightly guessed in the comments).
EDIT: thanks to #jfriend00 for pointing out a serious mistake in the previous version of my answer.
Your code essentially results in this:
ProjectsData.count().then(...);
console.log("required data not found");
So, of course the second console.log() is going to run and print. Nothing that happens in the .then() handler runs until long after the console.log() has already run. And, even then, it can't stop other code from running. Promises don't make the interpreter "wait". They just provide structure for you to coordinate your asynchronous operations.
If you want to branch with promises, then you have to branch inside the .then() handler, not after it.
You don't show enough of the rest of what you're doing to know how to recommend a complete solution. We need to see the rest of your request in order to help you with the proper branching based on asynchronous results.
You probably need something like this:
ProjectsData.count( {project_id: req.body.project_id} ).then(function(c) {
if ( c == 0 ) {
return res.send("The provided Project Id does not exist in our database.");
} else {
// put other logic here
}
}).catch(function(err) {
// handle error here
});

Resources