Many times I have created apps with express where I just spin up a server at a port and then on the client side do all the stuff. whether that be fetching with fetch/axios, rendering data, and even changing routes (react-router). I have never hugely explored node or the server part, until now....hopefully.
I get what it's doing partially. in terms of
app.get('/', (req, res) => res.send('Hello World!'))
this just sends the response to the browser window. and I have even managed to do this:
app.listen(port, () => {
console.log("Listening");
fetch(url, {
}).then((res => res.json()))
.then((json => console.log('json')))
.catch(() => {
console.log("bbb");
});
});
and this logs all the data into the sever window. however, I have a couple of questions
should I be doing this in the server or the client? whats the advantage?
secondly, once I have this data, how can I send it to the client? i.e. a react component
also, I cant seem to copy this code and get it work inside app.get()? am I doing it wrong? maybe I have misunderstood there
I understood more than questions, an answer to all would be great but I would just like to have some more knowledge on what goes inside express and the server
should I be doing this in the server or the client? whats the advantage?
You have to consider the followig things when requesting another server:
Serverside:
you can share the data to multiple clients
you can keep algorithms / secrets private
you probably have a better bandwith than your clients, so you can load big chunks of data and then only send the neccessary data to the client
Client:
Does not consume your servers ressources
secondly, once I have this data, how can I send it to the client? i.e. a react component
You can use AJAX, websockets (http://socket.io) or you have to use redirects.
also, I cant seem to copy this code and get it work inside app.get()?
If you expected to see the data at the client, you have to res.json(json).
Related
I am sorry for how I have framed the question in the title but I have started programming very recently so once again, I am really sorry.
I am developing a project with React js as my front-end and node js as my backend, I have been successful in doing some basic test api calls to confirm the connection between the two but now, how am I supposed to actually process different actions. For example, while a user is logging in, I need to first check if they are an existing user or not, sign them in if they are not, deleting a user account, changing username, etc.
I tried very hard to look for relevant articles but all I can find are basic "one-time" api calls, what am I supposed to do for an entire batch of operations? From what I have understood, the process of sending a request from React to getting it processed in Node js is like this:
react js ======>
(request for operation) node js ======>
(process the operation) ======>
send a response back to react
Please correct me if there are any mistakes in my question...
Thanks a lot!
This question is really broad, so I'm going to focus in on this part at a high level:
I tried very hard to look for relevant articles but all I can find are basic "one-time" api calls, what am I supposed to do for an entire batch of operations?
I'm guessing when you talk about requests and APIs you're talking about HTTP requests and REST APIs, which are fundamentally "stateless" kinds of things; HTTP requests are self-contained, and the backend doesn't have to keep track of any application state between requests in order to speak HTTP.
But backend applications usually do maintain state, often in the form of databases. For example, many REST APIs expose CRUD (create, read, update, and delete) operations for important business entities — in fact, Stack Overflow probably does exactly this for answers. When I post this answer, my browser will probably send some kind of a "create" request, and when I inevitably notice and fix a typo I will send some kind of "update" request. When you load it in your browser, you will send a "read" request which will get the text of the answer from Stack Overflow's database. Stack Overflow's backend keeps track of my answer between the requests, which makes it possible to send it to many users as part of many different requests.
Your frontend will have to do something similar if your project does things which involve multiple interdependent requests — for example, you would need to keep track of whether the user is authenticated or not in order to show them the login screen, and you would need to hold onto their authentication token to send along with subsequent requests.
Edit: Let's walk through a specific example. As a user, I want to be able to create and read notes. Each note should have a unique ID and a string for its text. On the backend, we'll have a set of CRUD endpoints:
var express = require(“express”);
var router = express.Router();
class Note {
constructor(id, text) {
this.id = id;
this.text = text;
}
}
// This is a quick and dirty database!
notes = {};
router.put("/note/:id", function(req, res) {
notes[req.params.id] = "hello"; // TODO: accept text as well
res.send("");
});
router.get(“/note/:id”, function(req, res) {
res.send(notes[req.params.id].text);
});
module.exports = router;
Then on the client side, one could create a note and then read it like this:
// this request will create the note
fetch("http://localhost:9000/note/42", { method: 'PUT', body: 'hello note!' });
// this request will read the note, but only after it is created!
fetch("http://localhost:9000/note/42")
.then(res => res.text())
.then(res => console.log(res));
Is it possible to use console.log() in the backend (I am using express) to output things in the frontend.
for example:
const express = require('express');
const app = express();
client.console.log('Hi');
How would I do it?
Thanks.
There is no built-in support for a server to cause something to show in the client console. I'm not sure what the actual use case for that is since the console is typically a debugging aid, not an actual end-user thing.
In any case, if you want to do that, you would have to have cooperating code on both the client and the server and then how that code works depends upon the context in which you want to put the info in the console.
From a page load
From a page load, the server could embed a small script in the page that would output into the browser console when the page loads and runs.
From an Ajax call
Here, you could include a property in some returned JSON that contains the desired console message and then the client code making the ajax call would have to grab that property and call console.log() with it.
From any random time on the server
If you're not in the context of an existing request from the browser or web page Javascript (as in the previous two points), then you would need some push channel connected between the web page and the server such as a webSocket connection, a socket.io connection or a SSE connection. Then, you could send a message to the client and the client would need some code listening for those incoming messages and then display them in the local console upon receiving them.
try it:
The 'send' method of 'res' object of Express, is one of so many ways to send a response to client in the request event.
const express = require('express')
const app = express()
app.get('/test', (req, res) => {
return res.send('Hello world!')
})
There is no support as jfriend00 said, but there is a way to go around this.
So lets say the user requests /test
You want to displayin his console Hello World
So you do:
const express = require('express')
const app = express()
app.get('/test', (req, res) => {
return res.send('<script>console.log(Hello world!)</script>')
})
And that acts as a full client console log. There ya go. (Single Time)
Or setup socket.io as jfriend said in his post if you want to constantly post console messages (multiple times).
I'm relatively new to full-stack development, and currently trying to figure out an effective way to send and fetch large data between my front-end (React) and back-end (Express) while minimizing memory usage. Specifically, I'm building a mapping app which requires me to play around with large JSON files (10-100mb).
My current setup works for smaller JSON files:
Backend:
const data = require('../data/data.json');
router.get('/', function(req, res, next) {
res.json(data);
});
Frontend:
componentDidMount() {
fetch('/')
.then(res => res.json())
.then(data => this.setState({data: data}));
}
However, if data is bigger than ~40mb, the backend would crash if I test on local due to running out of memory. Also, holding onto the data with require() takes quite a bit of memory as well.
I've done some research and have a general understanding of JSON parsing, stringifying, streaming, and I think the answer lies somewhere with using chunked json stream to send the data bit by bit, but am pretty much at a loss on its implementation, especially using a single fetch() to do so (is this even possible?).
Definitely appreciate any suggestions on how to approach this.
First off, 40mb is huge and can be inconsiderate to your users especially if there' s a high probability of mobile use.
If possible, it would be best to collect this data on the backend, probably put it onto disk, and then provide only the necessary data to the frontend as it's needed. As the map needs more data, you would make further calls to the backend.
If this isn't possible, you could load this data with the client-side bundle. If the data doesn't update too frequently, you can even cache it on the frontend. This would at least prevent the user from needing to fetch it repeatedly.
Alternatively, you can read the JSON via a stream on the server and stream the data to the client and use something like JSONStream to parse the data on the client.
Here's an example of how to stream JSON from your server via sockets: how to stream JSON from your server via sockets
I have been experimenting with Node.js on my machine for a little while and I have found my knowledge of HTTP requests, XHR objects, and the like quite lacking. So the main thing that's been nagging at me while using Node is that I can't seem to understand how to communicate from the client to the server (other than simple GET requests) and vice versa. What brings me to this question is my recent project, which is a simple 2 player chess game (no AI opponents).
What I want to do is to be able to send the game board data (a JSON string) to the server and have it save the data to a file. I understand how to get the file contents using an XHR object on the client-side. I also understand how to use Node's fs module to create and read files on the server-side. What I don't understand is how to use the XHR object to send the string to the server and have Node process and save it into a file. Is it even possible to call server-side code using client-side code in this way? Is trying to send an argument through a XHR object to the server an incorrect way of doing this?
If what I have asked is too broad of a topic to answer, I would also be open to links and books on the topic of server and client communication.
Expanding on SLaks answer a little:
Assuming you're using jQuery on the client and express on the server (both are useful frameworks to avoid reinventing low-level stuff), you could do something like this.
Client
$.ajax({
type: "POST",
url: "http://www.yourserver.com:3000/some/path",
data: { ...chessdatahere... }
}).done(function(msg) {
alert("Data Saved: " + msg);
});
Server
var fs = require('fs');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.post('/some/path', function(req, res) {
fs.writeFile('filename', res.body, function(err) {
if (err) {
res.send('Something when wrong');
} else {
res.send('Saved!');
}
})
});
app.listen(3000);
(Note that the code has not been tested, but it should show the general idea at least).
You can can use XHR to send an HTTP request with (eg) JSON data in the POST payload.
You can then write server-side Node.js code that handles this request, reads the payload, and does whatever you want with the data.
When you have a RESTful server which only responds with JSON by fetching some information from the database, and then you have a client-side application, such as Backbone, Ember or Angular, from which side do you test an application?
Do I need two tests - one set for back-end testing and another set for front-end testing?
The reason I ask is testing REST API by itself is kind of difficult. Consider this code example (using Mocha, Supertest, Express):
var request = require('supertest');
var should = require('chai').should();
var app = require('../app');
describe('GET /api/v1/people/:id', function() {
it('should respond with a single person instance', function(done) {
request(app)
.get('/api/v1/people/:id')
.expect(200)
.end(function(err, res) {
var json = res.body;
json.should.have.property('name');
done();
});
});
});
Notice that :id in the url? That's an ObjectId of a specific person. How do I know what to pass there? I haven't even looked into the database at this point. Does that I mean I need to import Person model, connect to database and do queries from within the tests? Maybe I should just move my entire app.js into tests? (sarcasm :P). That's a lot of coupling. Dependency on mongoose alone means I need to have MongoDB running locally in order to run this test. I looked into sinon.js, but I am not sure if it's applicable here. There weren't many examples on how to stub mongoose.
I am just curious how do people test these kinds of applications?
Have you tried using mongoose-model-stub in your server-side test? It will free you from having to remember or hardcode database info for your tests.
As for testing the client side, your "webapp" is basically two apps: a server API and a client-side frontend. You want tests for both ideally. You already know how to test your server. On the client you would test your methods using stubbed out "responses" (basically fake json strings that look like what your web service spits out) from your API. These don't have to be live urls; rather it's probably best if they're just static files that you can edit as needed.
I would use nock..https://github.com/pgte/nock
What you want to test is the code you have written for your route.
So what you do is, create a response that will be sent when the end point is hit.
Basically its a fake server..
Something like this..
Your actual method..
request({
method: "GET",
url: "http://sampleserver.com/account"
}, function(err, res, data){
if (err) {
done(err);
} else {
return done(null,data);
}
});
Then..
var nockObj = nock("http://sampleserver.com")
.get("/account")
.reply(200,mockData.arrayOfObjects);
//your assertions here..
This way you don't alter the functionality of your code.. Its like saying.. instead of hitting the live server..hit this fake server and get mock data. All you have to do is make sure your mock data is in sync with the expected data..