in an express.Js app ;i want to write a controller class that handles the request & response for other controllers for example add data to locals in res object or delete data from req.session etc.
is there a way i can do it without passing req or res as an argument
can i access them globally
The correct and possible way is to pass the req object as an argument to functions that need to use it.
Placing it in global variables will not work because multiple requests can be processed at the same time if for example requests use some asynchronous calls as part of their processing. So, multiple requests will stomp on other requests and will make it really hard to track down bug.
node.js is a server that can potentially handle many requests for many clients. Server may have many requests all in flight at the same time and thus plain globals you wish to use cannot be used for request-specific data.
Related
I'm using the id variable across different functions. The id is defined outside of the functions. Could this cause the variable to overwritten when receiving multiple simultaneous requests? Is the behavior the same when this is done in the browser instead of in Node.js?
var id;
server.get('/myapp', function (req, res, next) {
id = uuid.v4();
}
Yes, it causes conflicts
If your request handlers have any asynchronous operations in them which allow more than one request to be in flight at the same time, then YES, the use of a module level variable that more than one request may access will cause conflicts and one request could trounce the variable that another was using.
In a nutshell, don't do this
Module level variables are only for data that ALL requests can safely access and share. Data for a single request should be inside the request handler or a property on the request or response object or some similar-type object that is per-request and not shared among multiple requests.
Data needed only during the processing of a request
So, if you just need access to some data for the duration of this particular request, then you can put it in a local variable inside the request handler and you can pass it to any other functions you may call that need it while processing that request. Or, you can assign it as a property on the req object which is unique for each separate request and then pass the req object to any other functions you are calling that need access to the data.
Data needed from one request to the next, but different for each user
If you are trying to keep track of some data from one request to the next for one particular client, then you can't store it this way at all. You will likely need to use a session manager so you can create a lasting session that can be correlated with one particular browser from one request to the next. express-session is a popular session manager that makes it pretty easy.
The way a session manager works is that the first time a given browser hits your server, it is assigned a unique cookie. That cookie contains an encrypted session ID. Then, the session manager creates a session object that is indexed by that session ID. When a second request from the same browser comes in, then express-session gets that previously set cookie, decrypts the sessionID, looks up the corresponding session object and lets you then access any data you may have stored in the session object on behalf of this particular user.
I have ButtonClick.js and TakeData.js files. I defined my json data in TakeData.js as below
var dataObj = {};
var locationsObj = "locations";
dataObj[locationsObj] = {};
dataObj[locationsObj].source = [];
dataObj[locationsObj].target = [];
When I click the button in ButtonClick.js and the code snippet as below
button()
.container(g2)
.text(text2)
.count(1)
.cb(function()
{
console.log(dataObj[locationsObj].source[0]);
console.log(dataObj[locationsObj].source[1]);
console.log(dataObj[locationsObj].target[0]);
console.log(dataObj[locationsObj].target[1]);
console.log("SaveFile");
})();
I want to send json data into the nodejs file writing function as the following.
fs.writeFile('sample.txt', [need to insert my JSON], function(err) {
if(err) return console.log(err);
console.log('Hello JSON > sample.txt');
});
How can I do that? Is there another effective way?
Your backend needs to have an HTTP server listening on some port that is accessible to your frontend. Then your frontend needs to make an AJAX request to your backend (most likely a POST request) and send the required data in the request body.
Now, your backend needs to handle the request, get the data and write it to the file or do whatever you want with that.
Things to keep in mind:
use body-parser if you're using Express
remember about CORS
It's easier if you use a higher level framework on the backend like Express, Hapi, Restify, LoopBack etc. instead of the low level http module in Node.
It's also easier if you use a framework on the frontend like jQuery, Angular, React, Aurelia, Ember etc.
The first step is to set up a RESTful POST operation (an HTTP POST) on your server. This is the typical service mechanism for what is sometimes called an AJAX call. Once you have the server set up to receive a string via the POST, you can serialize your objects on the client side and deserialize (reconstitute) the objects on the server side.
To serialize, you can use stringify on the client side. A simple web search for "stringify" will show you different ways to use stringify in a browser-independent, backward compatible way.
stringify(obj)
On the server side, node.js has a global JSON object. Use parse to reconstitute an object or objects from the string. Other major languages now have similar parser methods. 1
JSON.parse(strJSON)
To get started, you can test the mechanism with just one simple object. Then you can aggregate the objects in a JSON array or associative array and send them all at once in a single POST.
[1] There are frameworks that encapsulate this process, but it may be of value to you to NOT initially use them so you get a clear picture of the mechanics of a RESTful POST over the HTTP protocol. It is the key thing that a browser does when you submit an HTML form, and RESTful operations are key communications elements in today's IT world.
I am writing a node module as a wrapper around a Python module (to make that module available from node.js). This module works as a standalone script or as an HTTP server.
When getting data from that script/server my function needs to return a value and can't do something in a callback function. At least that's how I understand it.
(One possible client is a gitbook-plugin, and when that encounters a "block" it has to call the plugin->my-client-module and insert its return value into the generated HTML document.)
So either I'm seeing something wrong because I'm too new to Node.js (coming from Python) or I need a way to make the HTTP request synchronous.
With the standalone script I can easily do it using ChildProcess.spawnSync, but not in an HTTP request.
Well, I know people are always recommending to do things asynchronously in Node, so I'd also be happy about pointers how to achieve my goal that way. As said I expect clients of my module to pass me some data, pass that along to invoke the script or do a POST request on the server and return the processed data to the client.
You can achieve synchronous HTTP requests using web-workers.
Here is more info on this topic:
https://developer.mozilla.org/zh-TW/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#Example_Synchronous_HTTP_request_from_a_Worker
Edit:
You can make synchronous requests from Node.Js. The following module should help:
https://www.npmjs.com/package/sync-request
I know that I can route to router.get('/object/:id', ...), router.post('/object/new', ...), router.delete('/object/:id', ...), and router.put('/object/:id', ...) and that when I browse to a specific object, the browser will issue a http get request. And I understand that I can post info through a form. But how can I implement the DELETE and PUT methods so that I can edit and delete objects? How do I specify the method used in the route? Do I have to change the route so that it is unique (ie, router.get('/object/delete/:id', ...) and router.get('/object/edit/:id', ...)) and just use get methods?
In your HTML form element you can use the method attribute to specify the method. <form method="put">. However, more typically these type of RESTful API endpoints are called from browsers with javascript as AJAX requests, which can use all of the available HTTP methods. This can be done with the XmlHttpRequest standard API, jQuery's $.ajax, or the front end framework of your choosing.
Do I have to change the route so that it is unique
No, you can have the same URL path with different HTTP methods and those can be handled by different callback functions to behave differently. Conventional REST URL schemes make heavy semantic use of the various HTTP methods requesting the same URL path (GET means get, PUT means replace, etc).
Beginner question
Running on server side, in node.js:
If I use a file-scope (or even global) variable which is set by an export.function(), where that exported function is called via ajax from a client, if multiple requests come from different clients, is the variable now prone to unexpected results?
I.e. do I need to set up an array so every time the export.function() is called it adds a new file-scope instance for that particular ajax request? Or is this magically handled by node.js where every ajax request gets its own instance of the server?
Requests will share the same instances so you'll need to guard against this. Note, however, that blocks of synchronous code will be executed completely before execution switches to handle another request so this simplifies the "guarding" you need to do.