Lesson 17
Making an Express Route to Create the Resource and Fixing the Frontend JavaScript
Summary
Summary of the API Development Lesson
Overview
In this lesson, we continue developing our API to handle data persistence in memory and client-server communication.
Key Points
-
Server Initialization:
- The server is run using
npm run
, but it does not persist data between resets.
- The server is run using
-
Data Persistence:
- Originally, the entries were defined inside the route handler, causing them to reset every time the server was restarted. They were moved to the global scope to maintain data through the server's runtime.
-
Client-Side Interaction:
- When a user adds an entry, it fails to communicate with the server. A new network request is needed to create this new entry on the server.
-
Creating a New Entry:
- A function called
createEntry
is defined to handle the API request using thefetch
API. - It sends individual entries via a POST request to
/entries
with JSON data.
- A function called
-
Server-Side Handling:
- The server needed a new route handler to manage POST requests to
/entries
, enabling it to accept incoming JSON data and create new entries. - A body parser middleware is implemented to parse the incoming JSON request into a usable JavaScript object.
- The server needed a new route handler to manage POST requests to
-
Error Handling:
- There are provisions for error message handling for both server connection issues and validation errors, which inform users of problems during their interactions.
-
Data Structure:
- Each new entry is assigned a unique ID simulating a database incrementing behavior.
-
Client Update:
- After a successful request, the response is used to update the client-side display.
- The flow is ensured to be synchronized, waiting for the server's response before updating the DOM.
-
Error Display:
- Error messages are linked with DOM elements so that users receive feedback if something goes wrong during operations.
Exercises
- Enhance the error handling mechanism for fetching entries when the server is down.
- Implement additional validation and filtering for incoming data to secure the API against possibly malicious requests.
This lesson builds upon previous knowledge, refining client-server communication and the proper handling of asynchronous operations, enhancing the user experience and ensuring data integrity.
Video Transcript
Welcome back to another lesson. Now let's get back to the development of our API.
So I have npm run that here it's running the server with no mod now let's get
back here to server.js and I'm gonna remove the hello that I had added before.
Now we have this endpoint to get all the entries but notice as I add a
manual entry and I keep adding entries if I restart see what happens it's all
gone and you can see this is happening because every time we hit the route it's
creating a whole new array every time and it's it's regenerating the entries so
it's not really persisting at least in memory so let's change this a little bit
so we can persist those in memory. So what I'm gonna do is I'm gonna cut this
entries array out of the route handler function and into the global scope of
the script that way entries will only be defined once and we'll have these three.
Now that's nice but as we add something new and we refresh it's all gone and
that's because we're actually not even hitting the server to add a new entry.
You can see as you click the network tab and you type something and click right
no new network requests appear right so we need to make a new network request
to the server and asking the server please create this new entry and the server
can say okay fine or it can reject with an error message perhaps you had sent an
empty message or some very very long message that the server refuses to accept
and that's called validation right in any case let's get back to what we're
doing let's take a look at the client side script.js when we click write what
does what what happens remember that we had added an event click event to the
submit button every time you click that it's it's grabbing that the value that
was typed in the text area then it's checking for errors validation right and
finally it's calling add new entry but when it calls add new entry all it does
is adds it adds a new entry to the page but actually it didn't call it we need it
didn't call the server so we need to do a name between here so before we actually
add anything to the page we need to first make a request to the server.
So how are we going to do it? Well we're gonna follow the same approach we did in
FATCH entries except it's going to be an entry to create not to obtain what's
ready in the list of entries. So let's create a new function here I'm gonna
call function create entry okay the function create entry will be responsible
for making a request to the server. So let's do it. Well how can make requests
to the server use FATCH? Now FATCH takes one the first argument is the where is it
right so what's the URL we're gonna say HTTP colon slash local host colon 3000
that's where our server is listening and we're gonna say slash entries in this
case it's a bit different because because it's going to be what's called a post
request instead of get so because of this special case I'm gonna add a second
argument to FATCH and that is going to be the argument for options and in the
options I'm gonna say the method is post so I pass as a second argument to
FATCH an object this object has the property method that has the value
post so that when it makes the request it will be a post request instead of get
okay that's the first step now you need to send something right and that's the
text that you typed how can we get that let's take that as an argument to the
function create entry actually let's do the following let's say entry as an
object let's assume entry is an object entry is an object like this has a text
property with the value of what it was typed there okay
now we have to take that entry and we have to to convert that object to a
string and that string will have the format JSON that way the server can
interpret your request properly because this is our server is what's called a
back-end API that serves JSON format it accepts JSON it produces JSON as output
to you so to do that let's add a new property to the fiat options given to
FATCH let's call it body and that's going to be the entry except we need to
convert it to JSON to do that we can use the module called JSON or object JSON
and there's a method called string if I and you call that with whatever you want
to string a fight in this case will be the object entry so this will become some
text with the format JSON it's almost the same thing except the keys will now
have quotes in closing the the value text right so this would become like this to
add here to the JSON format let's also add some headers just in case usually you
want to add the content type application JSON header so here at the end one more
option called headers for this request and the key will be the name of the
header content type and the value of the application slash JSON let me use double
quotes to be consistent with our code it doesn't matter in this case you can use
double single quotes choose a style okay I've got a comma just style so FATCH okay
great FATCH slash entries and its method post here's the entry for example it
could be like this and headers it's just saying this is content type of the body
right the body is to be interpreted as application slash JSON format so we're
gonna make that request to the server let's let's see what the server says
let's go back to server.js and you know you know notice we have app get entries
but we don't have posts so we have to add app.post slash entries and add a new
route handler rec res anonymous function here so let's just do a console log here
of whatever let's say the request object I don't know there might be a lot of
stuff in there let's just see what that is and then I'm gonna send something back
I'm gonna say okay 200 something like that just so we have some response from
the server now you can see no mon already restarted my server so I don't
have to do it manually now let's go here and back to script.js I didn't call this
yet right let's make sure to call it every time you click right and pass the
validation right add new entry well we cannot add it just yet let me just
comment that out and say create entry and I'm gonna say a new object with the
property text and that's going to be the entry text so I'm passing an object that
I just created an inline literal with the property text that's the entry text
whatever we typed in the text area let's try it out refresh your page type
something let's type hello world actually click right watch the network tab of
the browser you can see there's a new request let's click on that request
method is both correct we got 200 okay notice the request headers here has
content type application JSON that's what we wrote what we said notice the
payload is what we're sending and you can click build a source here and it's
exactly what we had there so it's the it's the entry right object in JSON
format notice the double quotes and closing the text key now let's see the
response from the server okay 200 that's fine now let's take a look at the
terminal because the server is running here and if you do a console log from
the server side it's gonna appear in the terminal so it's a lot of stuff and this
is the this is the request right object and that's a lot of stuff in here but
let's see let's start from the beginning if we can find the beginning
there you go the incoming message
other stuff readable let's see if we can find something that we recognize I think
it saw something before something about the body maybe I don't know or maybe it's
in a buffer format or some sort I don't know here's the headers let's see if we
can find content type here this is what we set in the client so it's appearing
here the server received that that's great
route path and so on so so we're getting something from server side so
that's great so let's continue now so from the server side what we're gonna do
is following given we have this array here called entries how about we add to
the end of the array every time you call post entries that makes sense right
let's do it remove the console log and let's say entries dot push whatever the
new entry is right we don't have it yet but let's assume we had it so entries
dot push whatever and then usually when you create if you follow rest rest what's
called rest convention rest for API convention if you want to create a
resource like a post slash resource name usually you send back the created
resource and that created resource includes the ID that was generated from
the database okay so let's send back the new entry let's say I'm typing the wrong
he sorry let's say that new entry somehow add an ID and that ID let's say just to
simulate simulate the database let's take the length of the entry because it kind of
let me see the first one is ID 1 and 2 and 3 if you take the length of entry plus
1 that's gonna be the new available ID right the next record of BID 4 that's an
available identifier no one has that yet but let's do that let's do entries dot
length that that gives you three right now initially and you add one of very
four so ID 4 and I need of course I need to say what is the text right that's
gonna be come from somewhere and that's somewhere it was was given by the
client to the body right but we don't know how to access that yet right so
let's try something what if somehow the request had the body and we could just
reference like this it'll be very convenient right let's do a console log
rack body colon rack dot body it'll be undefined right now and that would be
actually dot text because right the body would be an object and later on we
can do a refactor use dot store pool dot we're gonna teach you how to do that
later so we create the new entry push that and if finally we send that new
entry back to the client and the console log is just for debugging let's take a
look I mean write something right something happened here oh no not read
property text I'm gonna find that makes sense go back to the server you can see
rack body is undefined but how can we define it well we're gonna have to
download a third-party module could be something like body parser I go to
express let me see if they have in the express website let me search for body
parser something let's see if they mentioned anything here body parser yeah
there's a body parser middleware body parser take a look here there you go so
here's the module we want body parser and we can just after use body parser like
this so it's a middleware that will do the following since our client is sending
the record right the new record to be created in the JSON format the server
has to take that a message and convert it as well back into take that JSON
convert it back to a JavaScript object so it can use natively through Node.js
right mean it doesn't know what to do with the text itself but it takes that
text and parses it and it creates an object JavaScript object with the
information from that text okay JSON formatted text so we can do it like this
body parser.json so we already knew learn how to apply a middleware right
something that comes in between the request and the ultimate response let's
go here let's first install body parser so I'm gonna kill the server I'm gonna
say npm install I'm gonna call it its body dash parser
fine now you can see body parser is under the dependencies I'm using 1.19.0
here now go back to the server and you see you have the course middleware we're
gonna add the body parser app.use body parser.json call it like this now
this has to be imported I'm gonna go here at the beginning I'm gonna add const
body parser in camel case require body dash parser. Let me call it at the end my
style so we call it here too is my style now with that there's no every time you
get a request it's gonna pass through the body parser middleware and it's gonna
automatically convert the JSON string into an actual JavaScript object with
that it's going to set the rec.body property with that object now let's
restart the server here at PMRoundDev and let's go back to our site and reload
and I'm gonna do I didn't have to reload that I'm gonna add right you can see in
the console log here now rec.body is defined and it's an object whose key is
stacked and this is the text looking here at the row in the browser you can see
that the response that we get let me see response the raw response is the
actually created the new entry and you can see the new ID here ID for was added
as well and of course this is not the browser likes if you click the preview
tab it the browser will automatically make this look nicer to you but the
actual response is the one liner like that very nice now going back to the
text editor server.js I'm gonna do this with factory to spread so let's say that
your request had many many properties so you would you could type one by one
like this rec.body ASD whatever and keep doing that right let me but I'll be
tedious one other way you can do that is like this you can say dot dot dot
rec.body what this does is it copies all the properties from the object rec.body
and adds it in to this new object now mind you there's a you have to be
careful here because the client could be somebody else who's trying to do
something bad in your system so the client could add in some extra properties
in there or perhaps your client we're not giving all the necessary properties
even though it could bypass the client side validation mind you client side
validation is not safe at all anybody can bypass that so you have to make sure
to have validation on the server side okay so what I would advise here is you
have to have some way of first filter accepted or properties okay say the the
client gives you like text whatever but also says something else here something
else here you don't want all this extra stuff maybe it's a malicious client
trying to do something bad so you want to make sure to eliminate that before you
do anything else and even pass this to even a database to try to create a new
record so you want to filter the accepted properties that's something I leave it
as an exercise for you to do find a way to go to the object and only take the
properties that you want of course what we had before works just fine right and
that's actually a good way of filtering it like this that way only captures the
text and everything else is discarded right so I'll leave it like this I'll
leave it as an exercise for you to figure out a way to do that you could
make some sort of system that's nice that you can make like accepted properties
is some array like text whatever and then you can loop through it and generate a
new object that excludes all the other undesired or invalid properties something
like that you can you make a new function okay make a new field there a helper
function for example filter I don't know filter entry properties or whatever what
do you want to call it
exercise for you okay let's go back here to the client side I'm gonna refresh the
page let's see if this is actually doing anything you can see as a type and
click right even though it's not appearing in a client side on the DOM
right the document object model it the request is made if I refresh it appears
magically because when you make a request to the server to get all the
entries that those array of that array of entries is in memory right since I
didn't restart the server yet because I didn't make any change just now it still
keeps that in memory mind you that every time you make a change everything would
be out wiped out in the server side because the everything will be reloaded
and restarted so it'll go back to the original state but as long as I don't
restart the server it will persist at least in memory of course that's not
ideal right because you could restart the server many times throughout the
history you don't want to lose your data you don't want to keep your data all in
memory that's really bad what you want to do is store that in a persistent data
storage and that's a you can use a database right and that's eventually
going to store your data in the hard disk hard drive not in the computer memory
because computer memory is volatile it can come and go frequently so that's
nice well let's get back to the script and flex fix the client side we have the
create entry here but we want to make sure that it adds a new entry well of
course I could sequentially do this but that's not good why because of the
a synchronized nature of JavaScript here and also of the request
response model right because when you say create entry here you're calling this
function this function will call fetch but then it will continue execution of
the program and immediately after it will add new entry it probably would add
a new entry even before you got a response from the server so to
illustrate the point I can do the following let me see I can set a time
out here and let's do this
so I'm placing the fetch under timeout meaning that after a certain number of
milliseconds I want let me put five five seconds is five thousand milliseconds
after five seconds it's going to execute the fetch so it's going to delay it by
five seconds and because of the synchronized nature it's going to call
create entry and immediately after it's going to add a new enter even though the
server did not fulfill our request let's try it out so I'm going to click right
you can see no request but it was added already you can see no request in the
network tab and finally after five seconds the request is here and the
server said okay I created a new entry so this is not good at all right we have
to wait for the request to be fulfilled that is you make the client makes the
request to the server this and that might take some time right to reach the
server and then for the server to process your request and finally for the
server to send back some response and that takes time because of that it's a
synchronous asynchronous so there's some time you have to wait and we cannot just
do things like this so in order to add a new entry here we have first to wait for
the create entry that request to be fulfilled and successful before you can
add a new entry okay so how can we do that well I'm gonna do that through
promises this is called the concept of promises right we already handle promises
in the dot then here and dot then here so let's try it out they'll do it the
following let me remove the time out here do I remove it yeah I'm gonna remove it
right now I just wanted to illustrate the point of delaying so fat is actually
returning a promise when you call it so after that promise we want to do
something right so usually want to do a dot then and that's gonna give you a
response and that response we need to extract right while we got back
usually eyes the created entry with the ID so I'm gonna grab that even though we
already know what we typed I'm just gonna grab that because the server
included the ID so I'm gonna take and return response that Jason right
remember we did that here before we need to convert that into a JavaScript object
okay and finally we're gonna get the entry and what we're gonna do with the
entry is gonna append right here and let's see what we can do here I I could
move this at entry here but now that I'm thinking about these things again I
actually want to separate them because I want to make create entry have only the
concern of making a request to the server and that's it and I want to
separate that from the actual manipulation of the document here so I'm
gonna return here the fetch meaning the function create entry will return
whatever this operation does in this case returns let's see fetch returns a
promise and then a do dot then to handle that promise and from that you
return response that Jason who which by itself is also a promise right so this
is gonna return a promise and we can use the same dot then outside when you call
this to handle what's gonna happen after the promise has been successful right so
let's go back here to create entry this returns a promise so I can chain a dot
then right and that returns what that's gonna give me the entry as the are the
parameter and we can use that actually to call add new entry here in this
anonymous callback function and instead of entry text I want to say entry dot
text and actually later on if I wanted to I could include the whole thing that
would have the ID and everything but since I'm not using that I'll just let it
be because that we're keeping it simple simple right now so this returns a
promise that is handled with the dot then so after this is successful we got a
response from the server and we converted that response to an actual
JavaScript object so we can work with this JavaScript object appears here in
the callback as an argument entry and you can call add a new entry entry dot
text if you want to get set a breakpoint here if you were just curious about
what this is about so I'm gonna go to the browser go to sources script.js find
the block that contains that new entry and click line 55 here to click the
number and you can get a blade point in this red circle you can type something
click right now after calling create entry you can see there's a network
request here for it was successful and finally we are at this point line 55 and
you can hover over entry you can see actually that's actually the thing that
was created right from the server side and if you see entry dot text is
whatever we typed and that's great it's been passed by a new entry which will
create a new entry into DOM and click resume here and it's here now successfully
after the server accepted it that's great now what happens if the server was
down we simulated some sort of error let's see click the terminal kill your
server now try to add something again click right something happened post
error connection refuse fail to fetch well the user didn't know what happened
so that's something we have to fix you can see the request fail to low response
data so where what happened let's see so where is it making the request right
here notice that this could fail but we did not handle the failure how could we
handle the failure we can use a catch block so let's think about it here create
entry if this failed you could catch it here for example that would be one way
and the argument be the error oops I've been the wrong key let's console log that
and let's go here can I even put a breakpoint there to see that it's actually
going there as we restart and I'm gonna pull a break point in create entry catch
and we remove that other one I click here to deactivate the breakpoint on line
55 I'm gonna type something right you can see it goes there it tries to make the
request it fails because it fails instead of going to the dot then it goes
to the catch okay so if this promise is if this tries to make something this
promise is rejected with an error and because of that it goes to the catch block
and it skips everything every single day and after in between them so I'm have
the error here you can hover over it and let's console log it you can click
F8 or press F8 or click that you can see we got log type error failed to catch so
you can use that to show error message here let's try it out remember how we
did error messages we did a validation remember on lot lines 50 through 55 we
have an actual new entry our element that we add the class actually remove the
class to what make it appear
something like that let's take a look in the dome here if I click in here there
is something hidden you can make it show with this checkbox here you need to
type at least one character of course the text would be wrong for this new type
of error so my you want to change the text content of that let's let's check it
out so we could we could do that here or we could change the concern and let the
caller handle the error let's do that so instead of doing the catch here I'll let
whoever calls create entry to be the handler of the error so here in I have
the dot then if anything happens I'm gonna put a dot catch and we're gonna do
the error thing so I'm gonna target the error span as you could actually do the
same thing over again copy this code since the variable is in scope here I
probably could use it again but why don't want to refactor this later because
I don't want to tie B2 depending on things that are have different concerns
but it's fine let's do error span that grabs the the remember that spend with
error that's hidden and what I'm gonna do is I'm gonna change the text content
to be whatever error the message we got so error has a property called message
because it's a type error or whatever error error usually has a type a message
property in JavaScript error object and I'm gonna say error span the class list
dot remove new entry error hidden class so it can appear I'm assuming the error
exists so you might want to add a guard here in case it doesn't exist but I'm
assuming it exists but we got to be careful we should make maybe add an if
statement here otherwise if there there is anything there is gonna create an
error right it's gonna error out let's refresh and okay type something you can
see now fail to fascist here okay now the user knows what happened
so we changed the text and we made it up here if I rerun my server let's do and
now servers back and I try to add something now it's working okay I you
notice that the entries let me remove other break points remove all and if I
kill the server and I restart you can see the user doesn't know what happened so I
want you to as an exercise add an error message here saying like whatever
could be that same message so the user knows that the server is down or it
could not fetch the entries so that would be whoever calls fetch entries right
here you want to add a catch block dot catch and then you're gonna do the same
thing similar thing that we did here you're gonna change the you want to maybe
you want to create a new a new area of the page for the error or you could use
the same error that we had here I probably would use the I would do the way
I would do it is I would actually make a new element for the error that's related
to the actual list because I cut when I think about the user interface elements
or components this text area with the button is something separate from the
list itself so the list itself should have its own error message it should
have its own error and that's separate separated from the error related to the
actual text area to the submission of the text okay so that's an exercise for
you let me see if I can add here somewhere where's the fetch
exercise dot catch error here do whatever this is a multi-line comment you
know there's slash slash for single line and there's this slash star and star
slash everything in between is a comment when will be ignored
okay let's summarize and go over what we did so far let's see if the server is
running let me restart the server now so we added a new route to create a new
entry on the server side and when we type here click right and actually make
so request to the server and the server here on has a new route that's post
let me remove the console log we don't need it anymore it creates a new entry
takes a new ID that is available and includes that in the new entry takes the
reactive body the text reactive body is is set by body parser a middleware that
we used it's the npm package body-parse require it and then you can use it
up here and every time the request comes that text in JSON format will be
converted be parsed into an extra JavaScript object that's easy to work
with and that object is available in rack dot body we took the text from that
object and created the entry and pushed to the array that's in memory for now we
don't have a database yet this is just for us to have something to work with and
that was added to the end of entries so that will persist as long as the servers
is running was not restarted right if I had something and refresh still there
that's very nice so we fixed the front end to because it was not doing it was
always adding something even though the server did not approve it beforehand so
we have created entry that makes a request HTTP request after that if
everything successful we go to the then and actually add that to the
document in the page if there is any errors we do a dot catch block here and
remove this extra to be cool and we show the message that in that next to the
right button as an exercise left for you to catch the error that might occur if
when you fetch the interest for the first time as you reload the page I
suggest you kill your server and restart the app to make simulate some sort of
error with that for that's it for this lesson I hope to see you next time have
a good one
No comments yet (loading...)
No comments yet (loading...)
Did you like the lesson? 😆👍
Consider a donation to support our work: