I've just started working with Node.js so please forgive any stupidity!!! I'm trying to create a new application using Node.js. Im using the Express framework with a Postgresql database. The problem is that in my view, I wanted to to call a function. So I used a helper function that is called from my jade file. But because this function accesses the database, I tried to use callback inorder to make it work.
However, I can't seem to call a function from my jade template with the last argument as a function. The helper function worked fine when there was only one parameter being passed and it wasn't a callback function. But because the database query took a while, the the data was never displayed. But when I try to call a function with callback from my jade template, I get a syntax error.
My function call in my jade template:
#{ nameAndVersion(result.bu_entrep_id, function(error, result)) }
My helper function (It's simple because I was trying to get it to work):
exports.helpers= {
nameAndVersion: function(entid, callback) {
var x=1;
callback(null, x);
console.log(1);
}
};
My error:
500 SyntaxError: Unexpected token )
So, basically, I want to call a helper function from my jade template and have that function be a callback function.
You want to do :
Parse template
Retrieve data
Render template with data
Express templating is expected to do :
Retrieve data
Parse and render data
You should not have to execute complexe code once you've started rendering (what if you database is unavailable ?).
Jade helpers only have a formating purpose, not functionnal.
What you should do, instead of calling an helper, is giving the necessary data when calling the renderer.
app.get('anyPage', function(req, res) {
database.doSomeDataBaseQuery( /* Data base callback */ function(data, err) {
if(!err) res.render('pageTemplate', {dataBaseData:data});
}
});
Related
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.
I am trying to call a service in js in a asp.net model.
can you please help me find the right structure,
here is my general code.
GetSomething: function () {
var something;
System.SomeService.GetSomething(new Report.DocumentsRequest(), null, function (response) {
return something = Report.GetResponse(response);???
});
return something = Report.GetResponse(response);???
//
},
tank you for the help
It's hard to tell out of context, but it looks as though you're attempting to mix C# code with JavaScript code. If that's the case, you cannot do that. Instead, you need to provide an endpoint (controller action) that accesses your service and returns the results as something like JSON. Then, you need to utilize AJAX (the XMLHttpRequest object) in your JavaScript to make a request to that endpoint.
I posted this question yesterday but I guess I just confused everyone. I got responses like "what exactly is your question?" So I am expanding and reposting today.
The following node.js snippet is from the file "accounts.js" which is in an ETrade api library that exists in the path /lib. It should return json containing data about the accounts of the authenticated user. The authentication part is working great. I'm confused about what exactly is being done in the last line of this function:
this._run(actionDescriptor,{},successCallback,errorCallback);
Ten years ago (the last time I was coding), we didn't have the construct "this" and I haven't a clue about "_run" and Google searches have not been helpful. Here is the function.
exports.listAccounts = function(successCallback, errorCallback) {
var actionDescriptor = {
method: "GET",
module: "accounts",
action: "accountlist",
useJSON: true,
};
this._run(actionDescriptor, {}, successCallback, errorCallback);
};
I understand that the function is accessed with "et.listAccounts ...." but then my understanding goes all to hell. It's pretty obvious that a get is being executed and json data returned. It's also obvious that the result is passed back through the successCallback.
In my app.js file, I have the following:
var etrade = require('./lib/etrade');
var et = new etrade(configuration);
Can someone please suggest a snippet to be used in app.js that will output the accounts data to the console?
It seems like the json data must be passed back through the successCallback but I'm lost on how to access it on the app.js side.
Suppose in app.js I want to put the accounts data in a variable called myAccounts. The exports.listAccounts function does not specify a return value, so I doubt I can do var myAccounts = et.listAccounts(). Likewise, myAccounts will be undefined if I try to do this: et.listAccounts(){myAccounts, error}. Finally, the listAccounts function contains two possible variable names I could use, "accounts" and "accountlist" but these turn out to be undefined at app.js.
When I put a function in successCallback in app.js to write a generic message to the console, the message appears in the log so I know I am making it into the listAccounts function and back successfully. In this case, the log also shows
"Request: [GET]: https://etwssandbox.etrade.com/accounts/sandbox/rest/accountlist.json"
From this I deduce that the data is actually being returned and is available at that end point.
Ten years ago (the last time I was coding), we didn't have the construct "this" and I haven't a clue about "_run"
this refers to the current object, further reading here. _run is just what they chose to call the function.
I have no experience with this module, but with a cursory glance at the git repo I suspect you will want to expand your app.js like so:
et.listAccounts(function(response) {
console.log(response);
});
In javascript functions are first order and so can be passed around like variables see here. listAccounts wants a function passed to it, and when it is complete it will call it with one parameters, as can be seen in etrade.js.
There is also the function errorCallback which is much the same but is called on an error. You could expand the above snippet like so:
et.listAccounts(function(response) {
console.log(response);
}, function(error) {
console.log(error);
});
I have a question I hope you can help with. Basically, I'm doing a query on a MongoDB collection and attempting to pass the results back to a jade view.
app.helpers({
clients: function(){
users.find({uid:req.session.uid}).toArray(function(err, post){
if(err){
console.log(err);
}else{
return post;
}
});
}
});
This is where I reference the helper object in the view
p #{clients}
Right now I'm just getting [object Object] as the value in the view. If I log the results, I'll get the expected document results but if I try to push it into an array or a var, I get the [object Object] result. Any ideas?
This won't work, because you use the following structure:
clients: function() {
(some code)(function() {
return variable;
});
}
The return variable; statement returns from the inner function. But you need to return variable from the outer function. So how to do this? Actually you can't. You should do the query in a view and store the result for example in request and then pass the request variable to the template. You cannot use asynchronous functions in helpers.
Another thing is that when you use a function in a helper, then in the template you should use
p #{ clients() }
because it is a function. Nevertheless it won't work in this case.
I read on ICanHaz.js documentation that i should load templates from a remote like this
$.getJSON('/myserver/templates.json', function (templates) {
$.each(templates, function (template) {
ich.addTemplate(template.name, template.template);
});
});
I have no idea how the json template should look like, would really appreciate an example ICanHaz.js json template.
Thanks
To save some time on debugging $.each requires two arguments to the callback function: iterator and actual object
$.getJSON('/myserver/templates.json', function (templates) {
$.each(templates, function (id, template) {
ich.addTemplate(template.name, template.template);
});
});
Of course you must remember to set promise since these templates are loaded in async mode.