MEAN

STACK

APPLICATIONs

CESA IUST

Winter 2017

UP AND RUNNING WITH

the plan ahead

THE N: Node js

  • NodeJS
    • runtime 
    • syntax
  • Consensus 
    • Event driven programming
    • Callback functions
  • Practical
    • FileSystem
    • HTTP
    • Modules

the plan ahead

THE E: EXPRESS

  • Express
    • The middleware arch.

THE M: MONGODB

  • NOSQL Database
  • MongoDB Shell 
  • mongoose

THE A: ANGULAR

SESSION 1: NODE JS

  • Google V8 powered javascript interpreter in Desktop

  • Support direct C binding

  • Fast (relatively!) and lightweight 

  • NO DOM! 

  • NPM package manager

  • Used in: Desktop, Mobile, Embedded systems, IOT, etc...

  • The complicated story of Node/ecmaScript versions...

SESSION 1: NODE JS

  • Fastest growing community and ecosystem in history

Syntax (#1.1)

  • Variables: let + var + nothing

  • data types: Number, List, String, Object

  • Functions: named functions, variable functions, anonymous functions

  • flow control: for / while / if

  • Event control: nextTick, timeout, interval

    • ​JS (node/browser) runs in a single thread

    • Event Loop

  • Callback functions

modules (#1.2)

Any file can act as a standalone module

function up (str) {
  return str.toUpperCase()
}

function mul (x, y) {
  return x * y
}

module.exports = {
  mul: mul,
  up: up
}

let util = require('./Utilities.js')

console.log(util.up('yo'))

modules (#1.2)

LET'S TALK ABOUT CLASS

// ES6 feature
class Person {
  constructor (name) {
    this.name = name
  }

  say () {
    console.log(`Hi!, I am ${this.name}`)
  }
}

module.exports = Person
// ES5 - more complicated than what you think!
function Person (name) {
  this.name = name

  this.say = function () {
    console.log(`Hi!, I am ${this.name}`)
  }
}

module.exports = Person

modules (#1.2)

LET'S TALK ABOUT CLASS

const PersonClass = require('./obj/person.class')
const PersonFN = require('./obj/person.fn')

let p1 = new PersonClass('kian')
let p2 = new PersonFN('asqar')

modules (#1.2)

LET'S TALK ABOUT CLASS

let Person = {
  setName: (aName) => { name = aName },
  say: () => {
    console.log(`Hi!, I am ${name}`)
  }
}

module.exports = Person
  • You will barely need to use `new` in practice
  • Avoid using it and stick to file modules
let singletonPerson = require('./obj/person.module')

singletonPerson.say()
singletonPerson.setName('sth')

file system (#1.3)

const fs = require('fs')

fs.writeFile('./trash.txt', 'yo', (err) => {
  if (err) throw err
  console.log(`[${err}] saved`)
})

// Avoid this
fs.writeFileSync('./trash.txt', 'yo')

fs.readFile('./trash.txt', (err, data) => {
  console.log(err, data)
})

http module (#1.4.1)

Let's see the CODE

var srv = http.createServer()

srv.listen(PORT, '127.0.0.1', () => {
  console.log(`HTTP server listening on 
    port ${srv.address().address}:${srv.address().port}`)
})

srv.on('request', (req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'})
  res.end('okay')
})

http module (#1.4.1)

Let's see the DOC

http module - challenge (#1.4.2)

complete this server to

  • accept request body

  • route requests based on a static route file

const serverRoutes = {
  'GET': [
    {
      path: '/',
      handler: (req, resp, body) => { ... }
    },
    {
      path: '/yo', 
      handler: (req, resp, body) => { ... }
    }
  ]
}

express (#1.5.1)

let express = require('express')
let app = express()

app.get('/', function (req, res) {
  res.send('Hello Express')
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})

next week

  • Learn about mongodb
  • Complete express app to a basic CRUD API
  • Scaffold a basic client app with Angular

SESSION 2: Express js investigation #2.1.1 

  • Notes about express
    • Using body-parser to read request body
  • the `req` object
    • `req.body`, `req.baseUrl`, `req.cookies`, `req.ip`, `req.hostname`, `req.method`, `req.path`, `req.query`
  • the `resp` object
    • `resp.send()`, `resp.end()`, `resp.redirect()`, `resp.json()`, `resp.sendFile()`, `resp.status()`
      • with `sendFile`: using `__dirname`
      • with `status`: chaining

SESSION 2: Express js investigation #2.1.1 

  • Properly use `app.use()`
    • Tell me a great way to handle all unknown requests!
  • app.use can also be used for authentication

New request

fn(req, resp, next)

fn(req, resp, next)

fn(req, resp, next)

express - challenge (#1.5.2)

  • Express is Middleware based
  • app.METHOD for a specific method
  • app.use for all methods
  • each middleware is basically: 
    • a function with sig. : (req, resp, next) => {}
    • will pass the {req, resp} to the next middleware when `next()` is called

write a simple logger middleware

mongodb

  • NoSQL
    • no more join and table crap
  • important terms: Database, Collection, Document
  • Schema Free!
  • Let's see the commands

mongodb - interactive tutorial

$ show dbs

// use or create new database
$ use mean

// insert a document
$ db.mean.insert({"foo": "yo"})

// find it
$ db.mean.find({})

// what about collections? 
$ show collections

// what the hell is `mean` in this code? 
$ db.wtf.insert({name: 'kian'})
$ show collections

// let's get rid of it...
$ db.wtf.drop()

mongodb - interactive tutorial

// Let's have some valid (or near valid) data
// insert the name and age of some of the folks around you
$ db.users.insert({"name": "kian", age: 21, id: 92521042})

// THE FIND() method 
$ db.<collectionName>.find(
    {name: "kian"},      <-- criteria
    {},                          <-- projection
).limit(2)                       <-- cursor 

$ db.users.find(
    {age : { $ge: 20} },    
    {age: 1}
).limit(2)

// operations like $ge can be found on the website

mongodb - interactive tutorial

// THE update() method 
$ db.users.update(
    {name: "kian"},               <-- criteria
    {$set : {name : "kiana"}},    <-- operation
)             


// THE remove method
$ db.users.remove(
    {name : "kian"}               <-- criteria
)

// Note that adapters often offer other ways for update and remove
// which we will use very soon

mongodb - mongoose module

let mongoose = require('mongoose')
// step 1: connection
mongoose.connect('mongodb://localhost/mean')
let db = mongoose.connection
db.on('error', (err) => { console.log('error with db', err) })
db.once('open', function () {
  console.log('DB Connected')
})

// optional step 2: Schema
const Schema = mongoose.Schema
const TaskSchema = new Schema({
  title: { type: String, require: true},
  done: {type: Boolean}
})

// step3: Model
let TaskModel = mongoose.model('TaskModel', TaskSchema)

mongodb - mongoose module #2.2.1

// create a new object 

let aTask = new TaskModel({...})
aTask.save((err) => {})

// get and edit 
TaskModel.find({...})
TaskModel.findById(_id, (err, aTask) => {
    aTask.title = 'yo'
    aTask.save((err) => {})
})

// remove
TaskModel.remove({...})
TaskModel.findById(_id, (err, aTask) => {
    aTask.remove((err) => {})
})
  • All operations are done using the Model object in mongoose

back to express - crud + spa #2.2.2

  • Our app is going to server only one html file, the index.html
    • `app.get('/')
  • 4 Simple API's for each task:
    • Create: `app.post('/task')` -> will create a new task and return it to the user
    • Read: `app.get('/task/)` will get the list of all tasks
    • Update: `app.put('/task/:taskId')` will update a task's info
    • Delete `app.delete('/task/:taskId')` will delete a task
  • Assume no authentication and no task <-> user relation for now

basic angular js #2.3.1

  • Comprehensive, MVC front end framework
  • Main component: angular.module

module:

my-app

ctrl:

homeCtrl

template:

home

template:

profile

ctrl:

profileCtrl

service:

taskModel

directive:

taskFilter

basic angular js #2.3.1

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Yo Express</title>

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootflat/2.0.4/css/bootflat.min.css" />

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
    <script src="/client/main.js" charset="utf-8"></script>

  </head>
  <body>
    <h1>Our single page application will be serverd here</h1>
  </body>
</html>

basic angular js #2.3.1

  • main.js is not being served!
    • Our web server has no idea what to do with 'GET /client/main.js'
    • express static file serve 

angular js functionality #2.3.2

  • two way data-binding
    • anything attached to `$scope` inside a controller function
      • static: {{ }} 
      • dynamic: using `ng-model` and `<input>`
  • Buttons, functions and more
    • any function attached to scope can be used in html
      • note that inside <X ng-*="...."> and {{ ... }} we are inside of a controller's territory, no need to mention $scope
    • event return values!
  • Iteration: 
    • <X ng-repeat='for item in list'> {{ item }} </X>

$http in angular #2.3.3

fooApp.controller('fooCtrl', function($scope, $http) {
    $http.<METHOD>('/a/url', {data: 'something'})
    .then(
    (resp) => {}  // response success
    (resp) => {}  // response fail
    )

})

you now know everything you need to complete the basics of our todo-app

$http in angular #2.3.3

next week

  • Add an authentication to our app

    • Fron-end

    • Back-end

  • Fix some issues with folder structure and learn about best practices

Made with Slides.com