How to make api request with callback as argument in node.js? - javascript

I want to use method getPlayers(callback) which is defined as:
getPlayers(callback)
callback - Required. Called with an object of players
players - An object containing all the players connected to the server, with their name as the key
Retrieve all players connected to the server.
Here is the link to complete module for further details :
https://www.npmjs.com/package/hltv-livescore#getplayerscallback

If you want to use it and access the data, you'll need to do something like this:
getPlayers(function(players) {
// Here your players will be available
console.log(players)
})
Bonus: If you're using ES6, you can use Arrow functions, that are more elegant, like this (single line):
getPlayers(players => console.log(players))
or (multi line):
getPlayers(players => {
console.log(players)
})
You can read more about the async nature of Javascript here

If you refer source code of npm package you can see this code
https://github.com/andrewda/hltv-livescore/blob/master/lib/index.js#L78
Livescore.prototype.getPlayers = function(callback) {
callback(self.players);
};
You can use getPlayers like this :
Livescore.getPlayers(function(players){
// you will get players here
});

Related

Function is not recognized in map reduce command, mongoDB (javascript)

I have some problems with a map reduce I tried to do in MongoDB. A function I defined seems to not be visible in the reduce function.
This is my code:
function getName(user_id){
var users = db.users.aggregate({$project:{"_id":"$_id", "name":"$name"}});
users.forEach((it) => {if (user_id == it._id) return it.name;});
return "user not found";
}
var mapFunc = function(){ emit(this.user_id, this.book_id) };
var reduceFunc = function(key, values){return getName(key);};
db.booksToRecover.mapReduce(mapFunc, reduceFunc, {out:'users_to_recover_books_from'});
This is what I get:
The function was defined in the locally running javascript instance, not the server.
In order for that function to be callable from the server you will need to either predefine it there or include the definition inside the reduce function.
But don't do that.
From the reduce function documentation:
The reduce function should not access the database, even to perform read operations.
Look at using aggregation with a $lookup stage instead.

NodeJS : how to use arguments like req, res, result in functions?

I'm fairly new to JS especially Node and Express. I am following some tutorials on how to build an API and at the same time learning about JS special features such as let/const/var, arrow functions etc.
In many tutorials I have seen things likes this :
somecode.then((result) => {someothercode})
With: "somecode" being for example a get request
Is "result" the name of the returned value or is it a convention that JS developper use?
By that I mean, does this for example work?
somecode.then((foo) => {someothercode})
Also for req, res variables what does this mean?
app.get("/users/:userId", [
usersController.getById
]);
Here is the getById function (using once again the "result"):
exports.getById = (req, res) => {
userModel.findById(req.params.userId).then((result) => {
res.status(200).send(result);
});
};
the getById method defined in the controller needs (req, res), does that mean, when i call it like the code above, the req and res arguments are implicitly used?
Also it needs a parameter :
req.params.userId
which is in the url of the route, how does it pass to another file?
I have a route.js file that uses a controller.js file that uses a model.js. How does the param go from route to controller?
And it won't work if I change the param name right? for example:
req.params.id
Sorry for long post, I'm trying to understand JS logic to get some good habits and write clean code.
Thanks!
Is "result" the name of the returned value or is it a convention that JS developper use? By that I mean, does this for example work?
From my experience, yes - result is often used. Often times you'll see thing like value, response, but ultimately it can be whatever you define. I would recommend sticking to convention, and also check out the MDN Promise tutorial if you are starting out with understanding NodeJS asynchronous operations.
Also for req, res variables what does this mean?
app.get("/users/:userId", [
usersController.getById
]);
That is a middleware chain. Check out the Express docs for more information.
the getById method defined in the controller needs (req, res), does that mean, when i call it like the code above, the req and res arguments are implicitly used? Also it needs a parameter :
req.params.userId
which is in the url It won't work if I change the param name right? for example:
req.params.id
Yes, that is using a named parameter. Without the full router code, it is hard to know how the getById method is linked to the defined route. The Express routing documentation will likely be a good start on that.
Is "result" the name of the returned value or is it a convention that JS developper use?
result is the name of a new variable you are creating to represent the value passed in from the Promise resolution. Yes, your foo example will work.
(req, res) => {} is the same (mostly) as a function that looks like this:
function getById(req, res) {...}
req, and res are just representational of the values that will be passed to this function. They could just as easily have been called (foo, bar).
It looks like you're struggling with understanding callback functions. Consider the following code then please crack open the source code for the packages that you are using. and it looks like you are using express.js
function something(callback) {
var x = 5;
var y = 'anything';
callback(x, y);
}
something(function(req, res) {
console.log(req);
console.log(res);
});
the something function is created and inside of that function scope, var x and y are created with any type. then when we invoke or use something function we are passing a function as a variable that gets passed in as variable callback then it can be used since it is a function so we call callback with x and y which can literally be any value and for effect, I am passing back a number and a string as req and res.
It's just a convention. Note that the code:
somecode.then((result) => {someothercode});
Is actually:
somecode.then(myFunction);
Since somecode is a Promise, your function may be called with zero or one argument. It is up to you to name this argument:
function myFunction (foo) {
// use foo here
}
somecode.then(myFunction);
Of course, unlike some other languages, javascript does not force you to name your function. You can just use a nameless (anonymous) function:
somecode.then(function(mango) { /* use mango here */ })
Arrow functions is a new syntax allowing you to write anonymous functions in a shorter style (it also behaves slightly differently with regards to scope and the value of this)
Express.js and http.Server
In node's http.Server library and Express.js framework, each server request will call a function you define and pass it two arguments: the request object and the response object. The variables req and res are just conventions people use when writing their own request handler functions. You can name them anything you like. For example you may prefer to use request and response instead or rx and tx:
app.get('/say/hello', (rx, tx) => tx.send('Hello'));
How many arguments do I write a callback function with??
The best way to know is to read the documentation of the module you are using. It is not the only way to know - you can of course read the source code instead. But it is often easier to read the documentation. Because of this, javascript modules tend to have really good documentation (otherwise they would be unusable and ignored by the community).
Express.js will actually pass three arguments to your callback (not two!!) - request, response and next where next is a function you can call if you want Express to continue processing instead of replying to the request. One interesting feature of javascript is that you are allowed to call functions with fewer or more arguments and it is not considered a syntax error:
function example (x) {}
example(); // not an error
example(1); // not an error
example(1,2,3,4); // also not an error
Express uses this feature by always calling your callback with three arguments while allowing you to declare said callback with only two arguments if you don't need the third, next argument.

Calling object functions with variables

I'm building a simple node.js websocket server and I want to be able to send a request from a client to the server and have it just take care of things (nothing that could cause harm). Ideally the client will pass the server an object with 2 variables, one of them for the object and the other for the specific function in that object to call. Something like this:
var callObject = {
'obj': 'testObject',
'func':'testFunc'
}
var testObject = {
func: function(){
alert('it worked');
}
}
// I would expect to be able to call it with sometihng like.
console.log( window[callObject.obj] );
console.log( window[callObject.obj][callObject.func] );
I tried calling it with global (since node.js doesn't uses it instead of a browsers window) but it won't work, it always tells me that it can't find callObject.func of undefined. If I call a console.log on callObject.obj it shows the objects variable, as a string, as expected. If run a console.log on the object itself I get the object back.
I'm guessing this is something rather simple, but my Google-fu has failed me.
My recommendation is to resist that pattern and not have client code pick any function to call. If you are not careful you have built yourself a nice large security hole. Especially if you are considering using eval.
Instead have a more explicit mapping between data sent by the client and server code. (Similar to what routes in express what give you).
You might have something like this
const commands = { doSomething() { ... } );
// Then you should be able to say:
let clientCommand = 'doSomething'; // from client
commands[clientCommand](param);
This should be pretty close to what you want to achieve.
Just make sure doSomething validates any parameters passed in.
For two levels of indirection:
const commandMap = { room: { join() { ...} }, chat: { add() { ... } }};
// note this is ES6 syntax
let clientCmd = 'room';
let clientFn = 'join';
commandMap[clientCmd][clientFn]();
I think you might just have to find the right place to put the command map. Show your web socket handler code.

Firebase function .onWrite not working?

Ok, I have looked at similar questions like Firebase function onWrite not being called and thought it was my fault getting the reference, but I have no idea what is happening here with my Firebase functions.
I am just trying to get a function to write to my database when a write has been made to database. I followed the firebase tutorial exactly:
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
//https://firebase.google.com/docs/functions/database-events
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// const gl = require('getlocation');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});
exports.enterLocation = functions.database.ref('/Users/{name}') //brackets is client param
.onWrite(event => {
// Grab the current value of what was written to the Realtime Database.
// const original = event.data.val();
console.log('SKYLAR HERE:', event.params.name);
// You must return a Promise when performing asynchronous tasks inside a Functions such as
return firebase.database().ref('/Users/{name}').set({ location: 'test loc' });
});
The function is being run, yet in my logs I get a pretty unhelpful error that it is getting the {name} param, and data is definitely written to my database, however my SERVER code is not writing:
I get -
ReferenceError: firebase is not defined at
exports.enterLocation.functions.database.ref
Which makes no sense as it is defined. I just want to add an extra child under the user I create, like I do already with "password"
What am I doing wrong?
Two problems here. First, you haven't defined firebase anywhere in your code. I think you meant to use admin instead to use the Admin SDK.
Second, it looks like you're trying to do variable interpolation into a string to build the name of the ref. Your syntax is wrong here.
I imagine you're trying to say this instead in your last line of code:
return admin.database().ref(`/Users/${name}`).set({ location: 'test loc' });
Note the backticks on the string quotes. That JavaScript syntax lets you use ${exp} to insert the contents of some expression in the string.
It turns out you don't even need to use the admin SDK here. Since you're trying to write back to the same location that triggered the function, you can just use the ref that comes from the event object:
return event.data.adminRef.set({ location: 'test loc' });
instead of this:
return firebase.database().ref('/Users/{name}').set({ location: 'test loc' });
use this:
return admin.database().ref('/Users/{name}').set({ location: 'test loc' });

Define server function for mongo based on pure javascript function

Suppose I have a pure javascript file that has several function definitions. It does not contain anything mongo-specific - these functions parse and evaluate a query on a document. I would like to use these functions for server queries (e.g. db.collection.find(...) or map-reduce). How may I do this so that the server functions can essentially invoke what's in the pure javascript file?
Example: In foobar.js -
function foo(query, doc) {
// some predicate, for now lets simulate by evaluating a boolean field called 'available'
return doc.available;
}
According to https://docs.mongodb.org/manual/tutorial/store-javascript-function-on-server/
I would have to do this:
db.system.js.save(
{
_id : "bar" ,
value : function (query, doc){
return doc.available;
}
}
);
Then invoke db.loadServerScripts();
Running the following gives me the desired results:
db.myCollection.find(function() { return bar("some query", this) ;})
However I'd like to avoid inlining the functions in this db.system.js.save call. These functions belong to a library that I do not maintain. If there are any changes to the javascript library, I would have to manually convert them to db.system.js.save calls.
I would like to run something like this in mongo shell:
load("foobar.js")
db.system.js.save(
{
_id : "baz" ,
value : function (query, doc){
return foo(query, doc);
}
}
);
Then:
db.myCollection.find(function() { return baz("some query", this); })
But I get a "ReferenceError: foo is not defined" in my queries that invoke baz. Function "foo" is clearly not in scope. Suggestions or alternatives?
Disclaimer: I understand that using native operations are preferred, in addition to moving complexity out of the javascript into my application. However I am not at the point where I have the resources to essentially fork the logic from javascript to application logic that decomposes to native ops

Categories

Resources