- Published on
Node.js 101
- Authors
- Name
- Somprasong Damyos
- @somprasongd
Node.js 101
บันทึกการศึกษา Node.js เพื่อนำมาใช้พัฒนา Web Application
ทบทวนเนื้อหา JavaScript
ติดตั้ง Node.js
- Install Node.js ดาวน์โหลด ณ ตอนนี้ใช้ Node.js v7.10.0
- เปิด CMD/Terminal ทดสอบรันคำสั่ง
node -v
และnpm -v
Text Editor
- ATOM
- Vistual Studio Code ใช้ตัวนี้
- Netbeans
Node.js คืออะไร
Node.js คือ JavaScript runtime ที่สร้างมาจาก Chrome's V8 JavaScript engine โดยหัวใจสำคัญคือการใช้ event-driven กับ non-blocking I/O
มี npm (Node Package Manager) ไว้ติดตั้ง module ต่างๆ ใน Node.js package ecosystem มาใช้งานได้
เปรียบเทียบ Object ใน Google Chrome กับ Node.js
Object | GG Chrome | Node.js |
---|---|---|
Global Object | window | global |
DOM Object | document | ไม่มี |
Process Object | ไม่มี | process |
REPL (Read-Evel-Print-Loop)
Node.js สามารถรันแบบ REPL โหมดได้ คือ มันไม่ต้อง complie โค้ด สามารถรันได้เลย
เข้าโหมด REPL โดยพิมพ์ $ node
REPL ย่อมาจาก
- R - read คือ รับ input จาก keyboard
- E - eval คือ สามารถประมวลผลโค้ดที่รับมาได้ทันที
- P - print คือ แสดงผลลัพธ์ออกมาได่เลย
- L - Loop คือ เริ่มกลับไปทำงาน 3 ขั้นตอนข้างบนใหม่ จนกว่าจะจบการทำงาน
ตัวอย่าง
$ node
> 10 + 30
40
> 50 * (10 - 3) / 3
100
> a = 120
120
> b = 200
200
> c = 300
300
> a + b + c
620
> total = _
620
> console.log(total)
620
undefined
>
การทำงานของ Call Stack & Event Loop
การทำงานแบบ Non-Blocking I/O
มีการทำงานแบบ Asynchronous Task คือไม่ต้องรอทำงานทีละบรรทัด
ภาพตัวอย่างเปรียบเทียบการทำงานแบบ synchronouse Vs. Asynchronous
ภาพจาก The Complete Node.js Developer Course 2.0 | Udemy
วิธีการเขียนโค้ดแบบ Asynchronous ทำได้ดังนี้
- Callback Function คือเมื่อทำงานเสร็จแล้วให้เรียกฟังก์ชัน callback ให้ทำงานต่อ จัดการไม่ดีอาจมีปัญหาเรื่อง Callback Hell
- Promise ES2015 เพิ่ม Promise มาดักจับการทำงานถ้าสำเร็จให้ทำอะไร ไม่สำเร็จให้ทำอะไร
- Async/Await ES2017 เพิ่ม async/await มาใช้ร่วมกับ Promise เพื่อหยุดรอให้ Promise ทำงานให้เสร็จ (ทำให้ async ดูเหมือน sync)
Node Module
ใช้ require ในการเรียกใช้งาน module อื่น ในโค้ดของเรา เช่น const fs = require('fs');
โดยจะมี module อยู่ 4 ประเภท ดังนี้
1. Core Module
ใช้ require('module name');
จะเป็น module ที่มีมาใน Node.js เลย ดูว่ามีอะไรให้ใช้บ้างจาก Doc ตัวอย่าง
File System Module
ใช้ในการอ่าน/เขียนไฟล์ มีทั้งแบบ Asynchronous และ Synchronous ตัวอย่าง
- ลิสไฟล์ทั้งหมดใน directory จะได้รายชื่อออกมาเป็น array
const fs = require('fs')
fs.readdir('c:/', (err, datas) => {
console.log(datas)
})
- การสร้าง directory
const fs = require('fs')
fs.mkdir('myfolder', (err) => {
if (err) {
console.log('Error:', err.message)
}
console.log('Create directory successfully.')
})
- อ่านไฟล์ json
const fs = require('fs')
// จะได้ออกมาเป็น buffer
fs.readFile('./data.json', (err, data) => {
console.log(data) // Show Buffer
})
// ใช้ toString() มาแปลงจาก buffer เป็น String
fs.readFile('./data.json', (err, data) => {
console.log(data.toString()) // show string
})
// หรือให้ใส่ utf-8 เพิ่มเข้าไป data ที่ได้ออกมาจะเป็น String
fs.readFile('./data.json', 'utf-8', (err, data) => {
console.log(data) // show string
})
// วิธีแปลง String เป็น json object
fs.readFile('./data.json', 'utf-8', (err, data) => {
if (err) {
console.error('unable to read file.')
}
try {
const json = JSON.parse(data)
console.log(json.firstname)
} catch (err) {
console.error('invalid json in file')
}
})
- ตัวอย่างเขียนไฟล์ json จาก object
const fs = require('fs')
// object
let user = {
name: 'Somprasong Damyos',
}
// แบบนี้จะใช้ไม่ได้ จะเขียนออกไปเป็น [object Object]
fs.writeFile('user.json', user)
// ต้องแปลง json เป็น String ก่อน
fs.writeFile('user2.json', JSON.stringify(user))
- ตัวอย่างเขียนไฟล์โดยใช้ Stream
const fs = require('fs')
let data = 'Hello World'
const stream = fs.createWriteStream('file-from-stream.txt')
stream.write(data, 'utf-8') // เขียนข้อมูลลงไป
stream.end() // จบการเขียน
stream.on('finish', () => console.log('Successfully created a file.'))
- ตัวอย่างอ่านไฟล์โดยใช้ Stream
const fs = require('fs')
let data = '' // สร้างตัวแปรมารับค่าที่อ่านได้
const stream = fs.createReadStream('file-from-stream.txt')
stream.setEncoding('utf-8') // ระบุ encoding
// อ่านข้อมูลมาใส่ไว้ในตัวแปร
stream.on('data', (list) => (data += list))
// เมื่ออ่านเสร็จแล้วให้จะให้ทำอะไรต่อ
stream.on('end', () => console.log(data))
- การเปลี่ยนชื่อไฟล์ หรือย้ายไฟล์
const fs = require('fs')
// rename(oldFile, newFile, callback)
fs.rename('./file-from-stream.txt', './new-file-from-stream.txt', (err) => {
if (err) {
console.log('Error:', err.message)
}
console.log('Rename successfully.')
})
// การย้ายไฟล์ rename(file, dir/file, callback)
fs.rename('./new-file-from-stream.txt', './myfolder/new-file-from-stream.txt', (err) => {
if (err) {
console.log('Error:', err.message)
}
console.log('Move file successfully.')
})
OS Module
เอาไว้ดูข้อมูลของระบบปฎิบัติการ
const os = require('os')
console.log(`System informations
Endianness: ${os.endianness()}
Type: ${os.type()}
Platform: ${os.platform()}
Arch: ${os.arch()}
OS Version: ${os.release()}
Home Directory: ${os.homedir()}
Total Memory: ${os.totalmem()} bytes
Free Memory: ${os.freemem()} bytes
Hostname: ${os.hostname()}
Uptime: ${os.uptime()}`)
Path Module
เอาไว้จัดการกับ path ของไฟล์ และไดเร็กทอรี่
const path = require('path')
// หาตำแหน่งไฟล์
console.log(`resolve: ${path.resolve('path-demo.js')}`)
console.log(`base name or filename: ${path.basename('path-demo.js')}`)
console.log(`extension name: ${path.extname('path-demo.js')}`)
/*
resolve: C:\Work\mymemo\Node.js\Core-Modules\src\path-demo.js
base name or filename: path-demo.js
extension name: .js
*/
DNS Module
เอาไว้จัดการกับ DNS Server เช่น หา ip address จาก dns
const dns = require('dns')
// get ip address from dns
// 1st param => dns
// 2nd param => callback function send error, ip address
dns.lookup('google.co.th', (err, address) => {
console.log(`Google address: ${address}`) // Google address: 74.125.200.94
})
HTTP Module
เอาไว้สร้าง web server
const http = require('http')
function runServer(req, res) {
let body = 'Welcome to your first web server'
let contentLength = body.length
res.writeHead(200, {
'Content-Length': contentLength,
'Content-Type': 'text/html',
})
res.end(body)
}
const server = http.createServer(runServer)
server.listen(3000, () => console.log('Server is now running at http://localhost:3000'))
อ่านไฟล์ index.html มาแสดง
const http = require('http')
const fs = require('fs')
fs.readFile('./index.html', (err, html) => {
if (err) {
throw err
}
http
.createServer((req, res) => {
res.writeHead(200, {
'Content-Type': 'text/html',
})
res.write(html)
res.end()
})
.listen(3000, () => console.log('Server is now running at http://localhost:3000'))
})
2. File Module
เป็น module ที่่สร้างขึ้นมาเองเอง ใช้ require('./notes');
ต้องระบุตำแหน่งของไฟล์ (ถ้าไม่ใส่นามสกุลไฟล์ require()
จะไปถ้าที่ .js ให้เอง) โดยไฟล์ notes.js ต้องมี module.exports
หรือ exports
ด้วย
3. Folder Module
จะระบุ path ไปยังโฟลเดอร์ที่มีไฟล์ index.js เช่น var say = require('./module');
หรือมี package.json โดยปกติใน package.json ที่ "main": "index.js"
ดังนั้น มันจะไปดูว่ามีการทำ module.exports
หรือ exports
อะไรไว้ใน index.js บ้าง
4. Third-party Module
เป็น module ที่ติดตั้งผ่าน npm โดยใช้ npm install [module name] [options]
และเรียกใช้งานโดย require('[module name]');
ระบุชื่อไปเลย เหมือน core module
const gulp = require('gulp') // ต้อง npm install gulp --save ก่อน
gulp.task('default', () => console.log('Hello Gulp Task!'))
การสร้าง Module
ต้องสร้างไฟล์ xxx.js ขึ้นมา และทำการ export ส่วนที่ต้องการให้ใช้งานออกไป ซึ่งสามารถทำได้ 2 วิธี
ใช้
exports.xxx = function(){};
ใช้
module.exports = {};
หรือmodule.exports = function ([param]){return yyy;};
หรือmodule.exports.xxx = function(){};
ซึ่งเบื้องหลังการทำงาน เมื่อเราเรียกใช้ require('path/file-module');
ตัว function require(path);
จะ return module.exports;
ออกมาให้ และมีการสร้างตัวแปร var exports = module.exports = {};
จึงสามารถใช้ exports.xxx = function(){};
ได้
NPM
เริ่มต้นใช้คำสั่ง
npm init
เพื่อสร้างไฟล์ package.json (มันจะมีคำถาม เช่น พวกชื่อ เวอร์ชัน คำอธิบาย ให้กด enter ข้ามไปก่อนค่อยแก้ที่หลังได้)ต้องติดตั้ง module ที่จะใช้งานจาก npm ใช้คำสั่ง
npm install [module name] --save
โดย--save
คือบอกว่าใช้เฉพาะโปรเจคนี้ และสั่งให้บันทึกลงในไฟล์ package.json ด้วย แต่ถ้าต้องการติดตั้งแบบ global คือต้องการใช้ทุกโปรเจค ให้เปลี่ยนไปใช้-g
แทนการระบุ version ทำได้โดย
npm install <module_name>@4.2.3
ซึ่งเลขเวอร์ชันจะเป็นแบบ major.minor.patchการอัพเดท ใช้
npm update <module_name>
สามารถใส่--save
หรือ-g
ได้การลบ ใช้
npm uninstall <module_name>
สามารถใส่--save
หรือ-g
ได้การระบุเลขเวอร์ชัน
- ระบุเลขเวอร์ชันที่ต้องการเลย เช่น
npm install express@4.12.0
- ระบุเป็นช่วง
<
,<=
,>
,>=
เช่นnpm install express@">=4.12.0"
- ระบุเป็นช่วง
~
(tilde) ถ้าระบุ minor จะเอา patch สูงสุด ถ้าระบุ major จะเอา minor สูงสุดมา เช่นnpm install express@"~1.2.3"
หมายถึงให้เอาเวอร์ชัน>=1.2.3
แต่< 1.3.0
- ระบุช่วง
^
(caret) จะอัพเดทส่วนที่ต่ำกว่า “หลักซ้ายสุดที่ไม่ใช่ศูนย์” เช่นnpm install express@"^1.2.3"
หมายถึง>=1.2.3 < 2.0.0
หรือnpm install express@"^0.2.3"
หมายถึง>=0.2.3 < 0.3.0
- ระบุเลขเวอร์ชันที่ต้องการเลย เช่น
Restarting App with Nodemon
ปกติเวลาแก้ไขโค้ดจะต้องรันใหม่ทุกครั้ง เช่น node app.js
ซึ่งถ้าไม่อยากมานั่งรันไฟล์ใหม่ทุกครั้งที่มีการแก้ไขก็ใช้ module ที่ชื่อ nodemon มาช่วย
เริ่มจาก
npm install nodemon -g
เวลารันไฟล์เปลี่ยนมาเป็น
nodemon app.js
แทนการ shutdown nodemon ใช้
Ctrl + C
การใช้งานกับ JSON
// แปลงจาก Object เป็น JSON
var obj = {
name: 'Somprasong',
}
var strObj = JSON.stringify(obj)
// แปลงจาก JSON เป็น Object
var personStr = '{"name": "Somprasong", "age": 31}'
var person = JSON.parse(personStr)
Config Environment
การกำหนดค่า Environemnt
- Windows ใช้คำสั่ง
$ set KEY=VALUE
เช่น$ set NODE_ENV=production
- OS X ใช้คำสั่ง
$ env KEY=VALUE
เช่น$ env NODE_ENV=production
วิธีการเรียกใช้งานในโค้ด โดยผ่าน object ที่ชื่่อ process.env
เช่น if(process.env.NODE_ENV === 'production')
Global Objects
__dirname
จะรีเทิร์น directory ปัจจุบันของไฟล์ที่เรียกใช้ ตัวอย่างconsole.log(__dirname);
__filename
จะรีเทิร์นตำแหน่งปัจจุบันของไฟล์ที่เรียกใช้ ตัวอย่างconsole.log(__filename);
Debuging
ใช้คำสั่ง
node debug app.js
ถ้าต้องการไป statement ถัดไป พิมพ์
n
แล้ว Enterถ้าต้องการจบโปรแกรมเลย พิมพ์
c
แล้ว Enterถ้าต้องการออกจาก debug mode ใช้
Ctrl + C
หรือ พิมพ์ quitในระหว่าง debug mode ถ้าต้องการเขียนโค้ดเพิ่ม หรือเอาค่าตัวแปรที่ผ่าน debug มาแล้วให้เข้า repl mode โดยพิมพ์ repl แล้ว Enter ถ้าต้องการออกใช้
Ctrl + C
ถ้าอยากระบตำแหน่งที่ต้องการจะ debug ให้แก้ไขไฟล์ที่จะ debug โดยจะเริ่มที่บรรทัดไหน ใส่
debugger;
แล้วรันคำสั่งnode debug app.js
มันจะหยุดที่ statement แรก จากนั้นให้พิมพ์ c แล้ว Enter มันจะพาไปยังบรรทัดที่พิมพ์debugger;
ไว้
Node Version Manager (nvm) for Windows
เนื่องจากบางครั้งเราอาจต้องการทดสอบโค้ดบน Node.js หลายๆ เวอร์ชัน สามารถใช้ nvm ช่วยในการสลับเวอร์ชันของ Node.js ที่จะรันได้
วิธีใช้เบื้องต้น
nvm ls
เพื่อดูว่าติดตั้งเวอร์ชันอะไรไว้บ้าง โดยตัวที่กำลังใช้งานอยู่จะมี "*" อยู่ข้างหน้าnvm install 6.10.2
ใช้สำหรับติดตั้ง Node.js เวอร์ชันที่ต้องการnvm use 6.10.2
ใช้สำหรับสลับไปใช้งานเวอร์ชัน 6.10.2- ลองตรวจสอบด้วย
node -v
Hashing คือ
การ hash คือการเข้ารหัสประเภทหนึ่ง ซื่งถ้าเป็นค่าเดิมต้องได้เลข hash เป็นเลขเดิมเสมอ ตัวอย่าง
ติดตั้ง package crypto-js
$ npm i crypto-js --save
การใช้งาน
const { SHA256 } = require('crypto-js')
var message = 'Somprasong Damyos'
var hash = SHA256(message).toString()
อื่นๆ
- การสร้าง Web Server โดยใช้ Express
- การทดสอบระบบโดยใช้ Mocha
- ใช้ MongoDB โดย Mongoose ORM
- Security and Authentication โดยใช้ JWT
- แนะนำ package validator ซึ่ง library สำหรับ string validators และ sanitizers เอามาใช้ร่วมกับการสร้าง schema ของ mongoose ได้
- ใช้ package lodash
_.pick(object, [paths])
ช่วยในการสร้าง object ใหม่ โดยการเลือก field ออกมาจาก object เดิม เช่นvar body = _.pick(req.body, ['email', 'password']);
- ใช้ package moment จัดการเรื่อง date format
- ตัวอย่างการใช้ socket.io