Jonas – Node.js part 1


Download here: https://nodejs.org/en/. Install. Check in command line node -v.

Section 1 – Intro

File I/O. Asynchronous non blocking. Pay attention to 2 different functions readFileSync vs readFile.



Simple server request and response.



file path: . refers to where nodejs is run/started, ${__dirname} refers to where the scirpt is located

Prepare placeholders in html template, to insert data (probably they do not need to even in brackets {} or %, just any uniquely identified string will do, because we will replace them like any text with .replace function)



Modular dev





dependencies, required for the app, install –save.
devDependencies, tools for development, not the app, install –save-dev
install across all projects in your machine (usually for devDep), npm i package –global





npm outdated, find outdated packages
npm install slugify@1.0.0, install past version, 1.0.0
before versino number: ^ accept minor, ~ accept only bug patches, * all versions
npm update slugify, update a package
npm uninstall slugify, delete a package

sharing project, dont include node-modules, just keep package.json and package-lock.json and “npm install” to reinstall required packages
nodemon –save–dev, nodemon helps to refresh server when saving
morgan, middleware
Section 3 – Backend Dev

Dynamic = backend rendered, API = get data from backend, rendered on frontend.
Section 4 – Node

Relies on V8 (written in JS,C++) to understand JS, libuv (C++) for async, i/o and various other processes.

Event-loop

Here we emit and listen(on) our own events:



Here we use built-in nodejs event emitter:





Streams, read and write at the same time.



Export Module


Section 5 – Async

Build a Promise
resolve and reject are actually functions
resolve puts data into then()
reject puts err into catch()


Consume a Promise
catch make use of the err, then make use of data
at each step, return a promise so that we can chain then & catch



other approach using async, await
write synchronous looking code with async effect
handle error with try { } catch { }
throw to mark the whole function as error, therefore escape
res_Pros will store promises, and 3 will be triggered and waited for at the same time with await Promise.all


Section 6 – Natours – API

Official reference: https://expressjs.com



Most basic requests in express
set up with app.listen
app.get returns data, status 200
app.post creates data
res.json, or res.end will end the request-response cycle.



Complete post request
newId created from the last ID
newTour created with assign function, pushed into all tours
status 201



pass params into request, access with req.params
? indicates optional param



app.patch update data, status 200



app.delete, status 204, return data: null



refactoring into functions



using .route, and chain requests of same route into 1





Middleware
do extra stuff between request and response
takes the form app.use( your middleware function, with 3 arguments req,res,next )
always call next() at the end



morgan middleware, console log request info



place holders for unbuilt routes



Using Router



Refactoring/Mounting into Route, Controller, Server, Express



add middleware by param on url,
val is avail, and should be used for param middleware only
no val for other extra middleware



Environment variable, can be acccessed with process.env (quite lag)
create config.env file and link to server.js file with dotenv.config({ path: ‘./config.env’ });
beware the loading process, env might need to load first so that app.js can use process.env.PORT





Troubles setting env var diriectly on 1 line as nodemon server.js or npm start, windows works differently with these command, nodemon always comes first



ESlint
https://eslint.org/
npm i eslint to check for possible bug

prettier
npm i prettier
create file .prettierrc, {“singleQuote”:true}
Section 7 – MongoDB

Download and install https://www.mongodb.com/download-center/community
Open cmd, run mongod.exe and mongo.exe, db -> test, set up completed (will need to create folder C:\data\db )

To start db in another path/folder, type env to start menu, edit environment variables. add path to mongo bin, run 2 files above in the desired folder



mongoDB docs on operators https://docs.mongodb.com/manual/reference/operator/query/

use natours-test, switch to or create a database
db.[collection].[function]
db.tours.insertOne( { name: “New Tour!!”, price: 100, rating 4.5} )
db.tours.insertMany( [{obj1}, {obj2}] )
show dbs
show collections



db.tours.find()
db.tours.find( {name: “Object name to find”} )
db.tours.find( {price: {$lte: 100} }), find document with price less than or equal to 100
db.tours.find( {price: {$lte: 100}, {rating: {$gte: 4.5}} } ), and 2 conditions
db.tours.find( { $or: [ {price: {$lte: 100}, {rating: {$gte: 4.5}} ] }, {name: 1} ), or 2 conditions and only get the name

db.tours.updateOne/Many(condition,set), use to change, or add new data, One applies for the first found object
db.tours.updateOne({name: “Any tour”}, {$set: {price:11111} })
db.tours.replaceOne/Many, replace all data

db.tours.deleteOne/Many(condition)
db.tours.deleteMany({}), delete all documents



Create MongoDB Atlas account
Create a new project, start a cluster, get some kind of key authentication
Link that cluster to Mongo Compass, with the authentication


Section 8 – mongoose

https://mongoosejs.com/

create Schema and Model



add data with new a instance of model and .save()





add data directly with .create()



getOne, Model.findbyId(), or .find(_id)

update, Model.FindbyIdandUpdate, new = true to return the new updated data, runValidators = true to revalidate the input with Model’s validators



Refactor into Model, which separates mongoose operations


const queryObj = { …req.query }; making hard copy of an object in JS

query string: localhost:3000/api/v1/tours?duration=5&difficulty=easy
can be accessed by express() with req.query

2 ways to make queries, object or chaining



it’s better to save the query first, and await later for the result. Build query first, execute later, because that query can be useful for other operations, where we actually await to get the final result.



more complicated query
localhost:3000/api/v1/tours?difficulty=easy&limit=10&duration[gte]=5

the parsed query string from req.query is close, but not identical to the required syntax of mongoose, i.e missing the $ sign, so we need some string manipulation to modify :


queryStr = queryStr.replace(/\b(gte|gt|lte|lt)\b/g, match => `$${match}`);



mongoose query documentation
query.sort(‘a -b’), mongoose sort by a (asc) and b (desc with the -). But the url has no space, hence seperated by comma url.com?sort=a,-b
query.select(‘a b’), may add select: false to schema to never select a field
.limit(l), .skip(s), skip first s docs, show next l docs, url.com?page=p&limit=l

Aliasing, reducing from
localhost:3000/api/v1/tours?fields=price,name,duration,ratingsAverage&sort=-price,-duration&limit=5 to
localhost:3000/api/v1/tours/top-5-cheap
add middleware to modify query



Refactor into a Class API

Aggregation pipeline, very similar to data piping in R or Python
Stages: https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/



model virtuals schema, fields that are calculated based on other fields, not stored on database, but available when query.



4 Mongoose Middlewares: Document, Query, Aggregation, Model
this objects in the function either point to the current doc, current query or the current aggregation object







to exclude all secret tours out of aggregation, instead of going back and change all the pipelines, we can simply make a middleware for the adjustment.



Data validation

String: maxlength,minlength,enum(possible categorical values), trim
Number: min,max
Date: min,max

for post and patch/update,
for patch/update there’s an option to re runValidators:true or just let update to anything by setting to false.

Custom Validators with customer properties:



validators library, npm i validator
https://github.com/validatorjs/validator.js?files=1


Section 9 – Err handling

Install node debug as dev dependency, npm i ndb –save–dev
ndb server.js



* applies to all other route to give 404 response





refactor for centralized err handling
1. app.all router will just pass an error object to next
2. err object will be handle by a centralize place later



Make a separate class for err handling
build custom status & statusCode
anything passed into next() is assume as an error, and the middleware stops there!



Need to return next() here, not just next() because it will continue to respond with res.status below.



Handle not found Error in getTour, i.e correct format ID request but not found

Handle bad request with invalid ID to getTour

Handle duplicate name error





Handle mongoDB login error -> unhandledRejection
process.on here is a listener
Handle any other err in code -> uncaughtException. A fun test is to put error code in app.js, then only when we start to interact with server, the error will be run.

Comments

Popular posts from this blog

Bryan Peterson – Learning to See Creatively

R – Stats, factor count,proportion

R - Supervised Learning