I have written a javascript function which will get executed inside db.eval() on mongodb on my nodejs platform.
my js function is:
function(data){
var d = {
vehicle_id:data.vehicle_id,
timestamp:{
$gte:data.start_time,
$lte:data.end_time
}
};
var routeStatus = [];
db.location.find(d,function(err,result){
db.result.insert({result});
});
}
which is minified to an string 'code' to be passed to db.eval()
var code = 'function(data){var d={vehicle_id:data.vehicle_id, timestamp:{$gte:data.start_time, $lte:data.end_time}}; db.location.find(d,function(err,result){return result;});}';
db.eval(code,[info],function(err,result){
log(result);
});
the info object contains all required fields getting called by function;
Now main question is db.location.find() is an asynch call so how could i get its result return to callback of db.eval(); ?
if i simply do return result from callback of db.location.find() then i get nothing returned as its being an async call.
got the answer, thanks to #NeilLunn for giving small but useful tip. the .toArray() worked
simple doing
var docs = db.location.find().toArray();
worked for me.
Related
Background: Been trying for the last 2 day to resolve this myself by looking at various examples from both this website and others and I'm still not getting it. Whenever I try adding callbacks or async/await I'm getting no where. I know this is where my problem is but I can't resolve it myself.
I'm not from a programming background :( Im sure its a quick fix for the average programmer, I am well below that level.
When I console.log(final) within the 'ready' block it works as it should, when I escape that block the output is 'undefined' if console.log(final) -or- Get req/server info, if I use console.log(ready)
const request = require('request');
const ready =
// I know 'request' is deprecated, but given my struggle with async/await (+ callbacks) in general, when I tried switching to axios I found it more confusing.
request({url: 'https://www.website.com', json: true}, function(err, res, returnedData) {
if (err) {
throw err;
}
var filter = returnedData.result.map(entry => entry.instrument_name);
var str = filter.toString();
var addToStr = str.split(",").map(function(a) { return `"trades.` + a + `.raw", `; }).join("");
var neater = addToStr.substr(0, addToStr.length-2);
var final = "[" + neater + "]";
// * * * Below works here but not outside this block* * *
// console.log(final);
});
// console.log(final);
// returns 'final is not defined'
console.log(ready);
// returns server info of GET req endpoint. This is as it is returning before actually returning the data. Not done as async.
module.exports = ready;
Below is an short example of the JSON that is returned by website.com. The actual call has 200+ 'result' objects.
What Im ultimately trying to achieve is
1) return all values of "instrument_name"
2) perform some manipulations (adding 'trades.' to the beginning of each value and '.raw' to the end of each value.
3) place these manipulations into an array.
["trades.BTC-26JUN20-8000-C.raw","trades.BTC-25SEP20-8000-C.raw"]
4) export/send this array to another file.
5) The array will be used as part of another request used in a websocket connection. The array cannot be hardcoded into this new request as the values of the array change daily.
{
"jsonrpc": "2.0",
"result": [
{
"kind": "option",
"is_active": true,
"instrument_name": "26JUN20-8000-C",
"expiration_timestamp": 1593158400000,
"creation_timestamp": 1575305837000,
"contract_size": 1,
},
{
"kind": "option",
"is_active": true,
"instrument_name": "25SEP20-8000-C",
"expiration_timestamp": 1601020800000,
"creation_timestamp": 1569484801000,
"contract_size": 1,
}
],
"usIn": 1591185090022084,
"usOut": 1591185090025382,
"usDiff": 3298,
"testnet": true
}
Looking your code we find two problems related to final and ready variables. The first one is that you're trying to console.log(final) out of its scope.
The second problem is that request doesn't immediately return the result of your API request. The reason is pretty simple, you're doing an asynchronous operation, and the result will only be returned by your callback. Your ready variable is just the reference to your request object.
I'm not sure about what is the context of your code and why you want to module.exports ready variable, but I suppose you want to export the result. If that's the case, I suggest you to return an async function which returns the response data instead of your request variable. This way you can control how to handle your response outside the module.
You can use the integrated fetch api instead of the deprecated request. I changed your code so that your component exports an asynchronous function called fetchData, which you can import somewhere and execute. It will return the result, updated with your logic:
module.exports = {
fetchData: async function fetchData() {
try {
const returnedData = await fetch({
url: "https://www.website.com/",
json: true
});
var ready = returnedData.result.map(entry => entry.instrument_name);
var str = filter.toString();
var addToStr = str
.split(",")
.map(function(a) {
return `"trades.` + a + `.raw", `;
})
.join("");
var neater = addToStr.substr(0, addToStr.length - 2);
return "[" + neater + "]";
} catch (error) {
console.error(error);
}
}
}
I hope this helps, otherwise please share more of your code. Much depends on where you want to display the fetched data. Also, how you take care of the loading and error states.
EDIT:
I can't get responses from this website, because you need an account as well as credentials for the api. Judging your code and your questions:
1) return all values of "instrument_name"
Your map function works:
var filter = returnedData.result.map(entry => entry.instrument_name);
2)perform some manipulations (adding 'trades.' to the beginning of each value and '.raw' to the end of each value.
3) place these manipulations into an array. ["trades.BTC-26JUN20-8000-C.raw","trades.BTC-25SEP20-8000-C.raw"]
This can be done using this function
const manipulatedData = filter.map(val => `trades.${val}.raw`);
You can now use manipulatedData in your next request. Being able to export this variable, depends on the component you use it in. To be honest, it sounds easier to me not to split this logic into two separate components - regarding the websocket -.
I am using API to extract data from Amazon API and I am using react js for it.
The problem is when I extract them and save it in the state it gives me an error of undefined, however, I am getting the result from the API. The function takes time to get data from API, I am using a method of extracting data which is suitable in node js but also working in react and I am getting a result, but unable to save it in a state. Here's the code below:
let getReport={
path:'/',
query:{
Action:'GetReport',
ReportId:'14941942615018036',
Version:'2009-01-01',
}
};
let temp=null;
mws.request(getReport, function(e, result) {
temp=result;
this.setState({amazon_data:result}) // gives undefined error
});
I think the reason is the function execution takes time and it runs the setstate line which makes the result null, any suggestions on how to fix this?
That happens because this.setState is not part of the this scope inside your function.
let getReport={
path:'/',
query:{
Action:'GetReport',
ReportId:'14941942615018036',
Version:'2009-01-01',
}
};
let temp=null;
const _this = this;
mws.request(getReport, function(e, result) {
temp=result;
_this.setState({amazon_data:result}) // this works because _this references the outer this
});
That should work or you can use arrow functions like below.
let getReport={
path:'/',
query:{
Action:'GetReport',
ReportId:'14941942615018036',
Version:'2009-01-01',
}
};
let temp=null;
mws.request(getReport, (e, result) => {
temp=result;
this.setState({amazon_data:result}) // this works because the arrow function binds the outer this to the function
});
I have the following problem: I want to get data from a specific node from firebase during runtime. It should display "stats" of a player that was selected before. Now I could use on() to get all the data in the beginning, but I want to save data transfers by only downloading the data of on player if I need to, so I tried to use once like this:
var firebaseRef = firebase.database().ref();
function getScoresOfPlayer(player) {
console.log(player);
var selectedPlayerScores = [];
firebaseRef.once('value').then(function(snap) {
snap.child('scores').child('thierschi').forEach(function(child) {
selectedPlayerScores.push([child.key, child.val()]);
});
});
return selectedPlayerScores;
}
The problem is that it retruns the array before the data was loaded into it. Also I checked the docs and didn't find a better solution.
Thanks in advance!
This is because the getScoresOfPlayer function returns selectedPlayerScores before the promise returned by the once() method resolves.
You should include the return within the then(), as follows:
var firebaseRef = firebase.database().ref();
function getScoresOfPlayer(player) {
console.log(player);
var selectedPlayerScores = [];
return firebaseRef.once('value') //return here as well
.then(function(snap) {
snap.child('scores').child(player).forEach(function(child) { //I guess it should be child(player) and not child('thierschi') here
selectedPlayerScores.push([child.key, child.val()]);
});
return selectedPlayerScores;
});
}
which means that you have to call your function as follows, since it is going to be asynchronous and to return a promise:
getScoresOfPlayer('xyz')
.then(function(selectedPlayerScores) {
....
})
I have the following code I'm trying to make a simple hit counter with. However, it doesn't work when I run it locally. When I start newHits as blank, it throws the error: Uncaught Error: Reference.set failed: First argument contains undefined in property 'hits.number'.
When I start it at 1, it just doesn't change the value of the hits in the database. Any help is appreciated: I'm new to programming. Thanks so much!
$(document).ready(function(){
var database = firebase.database();
var hits;
var newHits = 1;
var hitsRef = firebase.database().ref('hits');
hitsRef.once('value', function(snapshot){
console.log("hitsRef.once called");
hits = snapshot.val().number;
console.log("hits: "+hits);
newHits = hits+1;
console.log(newHits);
});
hitsRef.set({
number: newHits
});
});
the simple way to do that by using transaction see here
$(document).ready(function(){
var database = firebase.database();
var hitsRef = firebase.database().ref('hits/number');
hitsRef.transaction(function(hits){
console.log("hitsRef.once called");
hits++;
return hits
});
}
This is due to async nature of once(). According to your code, both once() and set() are called for the same value of i at once.
If you want to test it, place your set() within a setTimeout() like,
setTimeout(function(){
hitsRef.set({
number: newHits
});
}, 2000);
You will see that your problem is solved but this is not the correct way.Try this instead,
var i = 1;
hitsRef.once('value', function(snapshot){
console.log("hitsRef.once called");
hits = snapshot.val().number;
console.log("hits: "+hits);
newHits = hits+1;
console.log(newHits);
})
.then( function() { // change starts here
hitsRef.set({
number: newHits
});
});
Your set() method will only be called when once() is done retrieving hits. This works because once() returns a promise and it is thenable.
Read these then() in javascript and promises.
I'm having difficulties getting a value returned from this function in a separate file called InfoHandler.js which gets included in my second file.
module.exports = {
getInfo : function (val, callback) {
jsonRPC.getInfo(function(json){
Data1 = json.result[2];
Data2 = json.result[0];
Data3 = val;
json = JSON.stringify(json);
console.log(json);
callback(json)
});
},
I want to use this like this:
require("InfoHandler.js");
var Info = InfoHandler.getInfo('50');
Info should now contain the json string which gets prepared from the getInfo function via the callback. Unfortunately I get:
TypeError: undefined is not a function
for the callback.
It's most likely an Async IO Problem, can someone give me a hint ?
It's not an async IO problem, you are trying to call undefined as a function. You aren't passing a callback to getInfo so callback is undefined. Instead, do something like this:
InfoHandler.getInfo('50', function(json) {
console.log(json);
});
You need to pass a callback function to getinfo().
Instead of:
var Info = InfoHandler.getInfo('50');
Try:
InfoHandler.getInfo('50', function(Info) {
//Use Info here.
});