---
# System prepended metadata

title: Node.js

---

# Node.js

1. 物件
var a = { firstName: 'James', lastName: 'Bond' }

2. npm
- 只會在單一資料夾裡安裝
npm install 套件
npm -i --save 套件 

- 會在全域中安裝
npm install -g 套件

- 解除安裝
npm uninstall 套件

3. 內建的 http module
- ex.
var http=require('http');
var server=http.createServer(function(req,res){
if(req.url=='/'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is Home Page.</body></html>');
res.end();
}else if(req.url=='/student'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is student Page.</body></html>');
res.end();
}else if(req.url=='/admin'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is admin Page.</body></html>');
res.end();
}else
res.end('Invalid Request!');

});

server.listen(5000);

4. express
- 安裝
npm install express --save # -- save 會有 .json 檔存放套件資訊

- 路由
app.get('/', function (req, res) {
res.send`("<html><body><h1>Hello World</h1></body></html>")`;
});

var server = app.listen(5000, function () {
console.log('Node server is running..');
});

5. express 呼叫寫好的 html
- 安裝 body-parser
npm install body-parser

-ex.
var express = require('express');
var app = express();
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));
app.get('/', function (req, res) {
res.sendFile(__dirname+'/templates/test.html'); // ___
});

var server = app.listen(5000, function () {
console.log('Node server is running..');
});

6. 永遠執行 .js
- 安裝
sudo npm install -g forever # 要為全域的

- 執行
forever start test.js

- 查看執行中的檔案
forever list

7. 連線到 mariadb
- 安裝
sudo npm install mariadb

- ex.
const db = require("mariadb");
const pool = db.createPool({
host : 'localhost',
user : 'wang',
password : 'wang313',
database : 'clinic'
});

async function connect() {
let conn;
try {
let conn = await pool.getConnection();
let rows = await conn.query('select * from test');
console.log(rows);
}
catch(err) {
console.log(err);
}
}
connect()

8. jade-template engine
- 安裝
sudo npm install jade

- 建立資料夾放 .jade 檔，預設路徑為相同路徑下的 views 資料夾
vi ./views/test.jade

- ex.
app.set("view engine", "jade");
app.set("views", "jade"); // 設定資料夾名稱，預設為 views
app.get('/', function (req, res) {
res.render('test'); // path = ./jade/test.jade
});

9. 傳送資料
- vi .js
app.get('/', async function (req, res) {
var db = require('mariadb');
const pool = db.createPool({
host : 'localhost',
user : 'wang',
password : 'wang313',
database : 'clinic'
});
let conn = await pool.getConnection();
let rows = await conn.query('select * from test');
res.render('test',{test:rows});
});

- vi .jade
doctype html
html
head
title 新增病患資料
body
ul
each item in test
li=item.a

10. 接收資料
- 前端

- 後端
要記得加 index
- ex.
let order = await conn.query('select pa_num from doctors where dId = ?;', req.body.dId);
console.log(order[0].pa_num);

- 前端
用 JSON.stringify 把 [Object object] 的 value 拿出來

11. sort
- ex. rec 是 json, 用 rec 裡的 r_num 大小來排序
rec.sort(function(a,b){
return a.r_num - b.r_num;
});

- ex.
axios.get('/data').then(function(response) {
JSON.stringify(response.data[i].pId)
})

11. 時區問題
- 帶參數執行
env TZ='Taiwan/Taipei' node test.js

12. redirect 帶參數
var string = encodeURIComponent('1');
res.redirect('/?valid=' + string);

13. api 回傳 json 給 html
- api
return res.json({a : 1})

- html
<script>
(async() => {
const {data : rec} = await axios.get('/records');
})();
</script>

14. jwt cookie
- 設定 cookie, 到 api, 先回傳 cookie，res.cookie 完可以再回傳別的(res.json、sendfile)
const {data : rec} = await axios.get('/records');
const token = jwt.sign({ data, exp: Math.floor(Date.now() / 1000) + (60 * 15) }, 'my_secret_ key')
res.cookie('token', token, { httpOnly: false, secure: false, maxAge: 3600000 });

- 路由查看 cookie,
const user = jwt.verify(req.cookies.token, 'my_secret_key');

- html 接收 cookie
-> 先到路由設定回傳 cookie 值
router.get('/dId', function(req, res) {
const user = jwt.verify(req.cookies.token, 'my_secret_key');
return res.json({dId : user.data.aId});
});

-> 再到 html 接收
const {data : user} = await axios.get('/docMain/dId');

15. 轉到其他網址
- 第一種
res.statusCode = 302;
res.setHeader("Location", "http://localhost:8080/login");
res.end(); // setHeader 的 end 要 ()

- 第二種
res.redirect('/login')
res.end // 不用 ()

16. 好用的 js 套件網站
bestofjs

17. cookie
- 設置 cookie
```
const data = {update_rId : req.body.rId};
const update_rId = jwt.sign({data, exp: Math.floor(Date.now() / 1000) + (60 * 15) }, 'my_secret_key'); // 加密
res.cookie('update_rId', update_rId,  { httpOnly: false, secure: false, maxAge: 3600000 })
```
- 解 cookie
``const user = jwt.verify(req.cookies.token_name, 'my_secret_key');``

- error : mariadb too many connections
close the pool
``pool.end();``

- show Promise { <pending> }
要加上 then    
let userToken = AuthUser(data) console.log(userToken) // Promise { <pending> } 
userToken.then(function(result) { console.log(result) // "Some User token" })

- 直接呼叫函式
    document.addEventListener("keyup", async(event) => {int a = 0;}

- get url, 加上參數
    window.location.href = "/ckPatients?view=true"  
    
    # syntax sugar
    - 教學
        https://sophiali.dev/syntactic-sugar-examples-javascript
    - <b>IF</b>
        condition ? expressionIfTrue : expressionIfFalse
        ex. 
        ```
        int i = 2;
        i > 1 ? console.log('I am true') : console.log('I am false');
        ```
        output = I am true
    
    # socket.io-聊天室
    - 教學 <br/> https://single9.net/2017/12/node-js-%e8%88%87-socket-io-%e5%8d%b3%e6%99%82%e8%81%8a%e5%a4%a9%e5%ae%a4%e5%af%a6%e4%bd%9c/
    
- copy function
    ```
    function cpContent() { copy the content to clipboard
            var all_need_copy = getClass('copy');
            var total_str = '';
            // add the value needed to be copied
            for (let i = 0;i < all_need_copy.length;i++) {
                total_str += all_need_copy[i].value;
                total_str += "<new_element>";
            }
             // create a temporary textarea to place the value of copy
            var el = document.createElement('textarea');
            el.value += total_str; // add the value
            // make textarea unseen and unused
            el.setAttribute('readonly', '');
            el.style = {position: 'absolute', left: '‑9999px'};
            document.body.appendChild(el);
            el.select();
            var copy_suc = document.execCommand('copy');
            alert(copy_suc ? 'copy successfully'  : 'copy failed'); //alert successful or failed
            document.body.removeChild(el); // remove copt textarea
        }
    ```
    
    
