
JavaScript 一直以來都只能在瀏覽器上運行
在過去他並不像 C、C++、Python 能獨立在你電腦上運行
這導致他無法讀取、修改你電腦上的檔案
進行更複雜的操作
而 Node.js 就是為了打破這個窘境,他允許你在你的電腦直接執行 JavaScript
這使得 JavaScript 變得異常強大,能做出其他程式語言能做的事情
Node.js 的優勢:
Node.js 的應用場景:
就像我們要用新的玩具,需要先安裝它們一樣,我們也需要安裝 Node.js。
node -v,如果顯示版本號,說明安裝成功。NodeJs 最強大的莫過於 npm 這個巨大的套件管理系統
你可以把她想像成他是一個程式庫商店
任何的人,都可以將他寫好的程式碼上架上去
而今天如果你需要的功能,剛好別人已經寫好了
擬就可以直接下載下來,直接使用
俗話說的好,輪子不要重頭造
要善用前人寫好的工具,人類的科技疊代才有意義
NPM 除了提供程式庫商店這個大平台以外,他還會協助你管理你下載下來的套件
甚至可以幫你做一些簡單的專案設定
1npm init -y
21console.log("Hello World");1function add(a, b){
2 return a + b;
3}1export function add(a, b){
2 return a + b;
3}1import { add } from "./add.js";
2
3console.log(add(1, 2)); // 3 1import http from "http";
2
3// 我們等等會來解釋這段程式碼的功能
4const server = http.createServer((req, res) => {
5 res.statusCode = 200; // 你
6 res.setHeader("Content-Type", "text/plain");
7 res.end("Hello World\n");
8});
9
10server.listen(3000, () => {
11 console.log("伺服器運行在 http://127.0.0.1:3000/");
12});
13HTTP 伺服器就像是一個專門接收客人訂單的櫃檯。
以上面的程式碼為例子就像是開了一家簡單的餐廳,每當有客人來訪(發送請求),我們都會回應他們一句 "Hello, World!"。
什麼是 RESTful 架構?
為了管理好我們的餐廳,我們設計了ㄧ個設計準則來管理我們的餐廳
想像我們的餐廳不只賣一種食物,我們有菜單(資源),客人可以對菜單上的食物進行不同的操作(CRUD:建立、讀取、更新、刪除)。
基本上,每一次客人來訪時,都會很明確的聲明目的地
舉例來講,當你用瀏覽器打開某個網站,好比說 https://www.google.com/
其實你就是使用瀏覽器對 https://www.google.com/ 這個網址發起了一次 GET 請求
而 Google 的伺服器在收到你的請求後,將整個網站 HTML 傳給你
你就能看到他的網站
Nodejs 有一個別人寫好的套件, Express.js
他可以更簡單地去設定當客人傳什麼請求時,就做什麼事情
我們直接來看看吧
1npm install express 1import http from "http";
2import express from "express";
3
4// const server = http.createServer((req, res) => {
5// res.statusCode = 200; // 你
6// res.setHeader("Content-Type", "text/plain");
7// res.end("Hello World\n");
8// });
9
10// server.listen(3000, () => {
11// console.log("伺服器運行在 http://127.0.0.1:3000/");
12// });
131import http from "http";
2import express from "express";
3const app = express();
4
5app.get('/', (req, res) => {
6 res.send('Hello, World!');
7});
8
9app.listen(3000, () => {
10 console.log("伺服器運行在 http://127.0.0.1:3000/");
11});
12
13// const server = http.createServer((req, res) => {
14// res.statusCode = 200; // 你
15// res.setHeader("Content-Type", "text/plain");
16// res.end("Hello World\n");
17// });
18
19// server.listen(3000, () => {
20// console.log("伺服器運行在 http://127.0.0.1:3000/");
21// });
221import http from "http";
2import express from "express";
3const app = express();
4
5app.get('/', (req, res) => {
6 res.send('Hello, World!');
7});
8
9app.listen(3000, () => {
10 console.log("伺服器運行在 http://127.0.0.1:3000/");
11});
12
13// const server = http.createServer((req, res) => {
14// res.statusCode = 200; // 你
15// res.setHeader("Content-Type", "text/plain");
16// res.end("Hello World\n");
17// });
18
19// server.listen(3000, () => {
20// console.log("伺服器運行在 http://127.0.0.1:3000/");
21// });
221import http from "http";
2import express from "express";
3const app = express();
4
5app.get('/', (req, res) => {
6 res.send('Hello, World!');
7});
8
9app.listen(3000, () => {
10 console.log("伺服器運行在 http://127.0.0.1:3000/");
11});1import http from "http";
2import express from "express";
3const app = express();
4
5app.get('/', (req, res) => {
6 res.send('Hello, World!');
7});
8
9app.get('/cat', (req, res) => {
10 res.send('Cat is Cute!');
11});
12
13app.listen(3000, () => {
14 console.log("伺服器運行在 http://127.0.0.1:3000/");
15});1import http from "http";
2import express from "express";
3const app = express();
4
5app.get('/', (req, res) => {
6 res.send('Hello, World!');
7});
8
9app.get('/cat', (req, res) => {
10 res.send('Cat is Cute!');
11});
12
13app.post('/cat', (req, res) => {
14 res.send('Create A Cat!');
15});
16
17app.listen(3000, () => {
18 console.log("伺服器運行在 http://127.0.0.1:3000/");
19});1import http from "http";
2import express from "express";
3const app = express();
4
5// 創建一個陣列來儲存貓貓
6let cats = [];
7
8app.get('/cat', (req, res) => {
9 /** 回傳貓貓的資料 */
10});
11
12app.post('/cat', (req, res) => {
13 /** 接收貓貓的資料 */
14});
15
16app.listen(3000, () => {
17 console.log("伺服器運行在 http://127.0.0.1:3000/");
18});1import http from "http";
2import express from "express";
3import cors from "cors";
4const app = express();
5app.use(cors());
6
7// 創建一個陣列來儲存貓貓
8let cats = [];
9
10app.get('/cat', (req, res) => {
11 /** 回傳貓貓的資料 */
12});
13
14app.post('/cat', (req, res) => {
15 /** 接收貓貓的資料 */
16});
17
18app.listen(3000, () => {
19 console.log("伺服器運行在 http://127.0.0.1:3000/");
20});1import http from "http";
2import express from "express";
3import cors from "cors";
4const app = express();
5app.use(cors());
6app.use(express.json()); // 解析 JSON 格式的請求
7
8// 創建一個陣列來儲存貓貓
9let cats = [];
10
11app.get('/cat', (req, res) => {
12 /** 回傳貓貓的資料 */
13});
14
15app.post('/cat', (req, res) => {
16 /** 接收貓貓的資料 */
17});
18
19app.listen(3000, () => {
20 console.log("伺服器運行在 http://127.0.0.1:3000/");
21});1import express from "express";
2import cors from "cors";
3
4const app = express();
5app.use(cors());
6app.use(express.json()); // 解析 JSON 格式的請求
7
8// 創建一個陣列來儲存貓貓
9let cats = [];
10
11app.get("/cat", (req, res) => {
12 res.send(JSON.stringify(cats));
13});
14
15app.post("/cat", (req, res) => {
16 cats.push(req.body.cat);
17 res.send("successfully add cat");
18});
19
20app.listen(3000, () => {
21 console.log("伺服器運行在 http://127.0.0.1:3001/");
22});
231// 這裡是前端的程式碼
2const response = await fetch("http://127.0.0.1:3001/cat", {
3 method: "POST",
4 headers: {
5 'Content-Type': 'application/json' // 告訴 express,我送過去的資料格式,是 json 格式
6 },
7 body: JSON.stringify({cat:'test'}), // 請注意,送過去的資料必須先透過 JSON.stringify 轉成字串才能傳送
8
9}) // 以 GET 方式發送請求
10
11const data = await response.text(); // 將取得的資料以純文字解析
12console.log(data) // 印出來1// 這裡是前端的程式碼
2const response = await fetch("http://127.0.0.1:3001/cat", {
3 method: "POST",
4 headers: {
5 'Content-Type': 'application/json' // 告訴 express,我送過去的資料格式,是 json 格式
6 },
7 body: JSON.stringify({cat:'test'}), // 請注意,送過去的資料必須先透過 JSON.stringify 轉成字串才能傳送
8
9}) // 以 GET 方式發送請求
10
11const data = await response.text(); // 將取得的資料以純文字解析
12console.log(data) // 印出來MongoDB 是一種 NoSQL 資料庫。可以想像成一個巨大的數位檔案櫃,我們可以把資料(例如菜單上的菜)存儲在其中,並且隨時讀取、更新或刪除。
當中最大的特色便是他的資料是永久儲存
不會因為電腦關機、程市關閉資料就消失
首先,我們需要安裝 MongoDB。可以從 MongoDB 官網 下載並安裝。安裝完後,可以用以下指令來啟動 MongoDB
1npm install mongoose
21import mongoose from 'mongoose';
2
3mongoose.connect('mongodb://localhost:27017/restaurant', {
4 useNewUrlParser: true,
5 useUnifiedTopology: true
6});
7
8const db = mongoose.connection;
9db.on('error', console.error.bind(console, 'MongoDB 連接錯誤:'));
10db.once('open', () => {
11 console.log('已成功連接到 MongoDB');
12});1import mongoose from 'mongoose';
2
3mongoose.connect('mongodb://localhost:27017/restaurant', {
4 useNewUrlParser: true,
5 useUnifiedTopology: true
6});
7
8const db = mongoose.connection;
9db.on('error', console.error.bind(console, 'MongoDB 連接錯誤:'));
10db.once('open', () => {
11 console.log('已成功連接到 MongoDB');
12});
13
14const catSchema = new mongoose.Schema({
15 name: String,
16 age: Number
17});
18
19const Cat = mongoose.model('Cat', catSchema);1import express from 'express';
2import cors from 'cors';
3import mongoose from 'mongoose';
4
5const app = express();
6app.use(cors());
7app.use(express.json()); // 解析 JSON 格式的請求
8
9// 連接到 MongoDB
10mongoose.connect('mongodb://localhost:27017/restaurant', {
11 useNewUrlParser: true,
12 useUnifiedTopology: true
13});
14
15const db = mongoose.connection;
16db.on('error', console.error.bind(console, 'MongoDB 連接錯誤:'));
17db.once('open', () => {
18 console.log('已成功連接到 MongoDB');
19});
20
21// 定義資料模型
22const catSchema = new mongoose.Schema({
23 name: String,
24 age: Number
25});
26
27const Cat = mongoose.model('Cat', catSchema);
28
29// 查看所有貓咪
30app.get('/cat', async (req, res) => {
31 try {
32 const cats = await Cat.find();
33 res.json(cats);
34 } catch (err) {
35 res.status(500).json({ message: err.message });
36 }
37});
38
39// 新增一隻貓咪
40app.post('/cat', async (req, res) => {
41 const newCat = new Cat({
42 name: req.body.name,
43 age: req.body.age
44 });
45
46 try {
47 const savedCat = await newCat.save();
48 res.status(201).json(savedCat); // 201 表示資源已創建
49 } catch (err) {
50 res.status(400).json({ message: err.message });
51 }
52});
53
54app.listen(3000, () => {
55 console.log('伺服器運行在 /');
56});
571import express from 'express';
2import cors from 'cors';
3import mongoose from 'mongoose';
4
5const app = express();
6app.use(cors());
7app.use(express.json()); // 解析 JSON 格式的請求
8
9// 連接到 MongoDB
10mongoose.connect('mongodb://localhost:27017/restaurant', {
11 useNewUrlParser: true,
12 useUnifiedTopology: true
13});
14
15const db = mongoose.connection;
16db.on('error', console.error.bind(console, 'MongoDB 連接錯誤:'));
17db.once('open', () => {
18 console.log('已成功連接到 MongoDB');
19});
20
21// 定義資料模型
22const catSchema = new mongoose.Schema({
23 name: String,
24 age: Number
25});
26
27const Cat = mongoose.model('Cat', catSchema);
28
29// 查看所有貓咪
30app.get('/cat', async (req, res) => {
31 try {
32 const cats = await Cat.find();
33 res.json(cats);
34 } catch (err) {
35 res.status(500).json({ message: err.message });
36 }
37});
38
39// 新增一隻貓咪
40app.post('/cat', async (req, res) => {
41 const newCat = new Cat({
42 name: req.body.name,
43 age: req.body.age
44 });
45
46 try {
47 const savedCat = await newCat.save();
48 res.status(201).json(savedCat); // 201 表示資源已創建
49 } catch (err) {
50 res.status(400).json({ message: err.message });
51 }
52});
53
54// 修改貓咪的名字
55app.put('/cat', async (req, res) => {
56 const { originalName, newName } = req.body;
57
58 try {
59 const updatedCat = await Cat.findOneAndUpdate(
60 { name: originalName },
61 { name: newName },
62 { new: true }
63 );
64 if (updatedCat) {
65 res.json(updatedCat);
66 } else {
67 res.status(404).json({ message: '找不到該名稱的貓咪' });
68 }
69 } catch (err) {
70 res.status(400).json({ message: err.message });
71 }
72});
73
74app.listen(3000, () => {
75 console.log('伺服器運行在 /');
76});
771import express from 'express';
2import cors from 'cors';
3import mongoose from 'mongoose';
4
5const app = express();
6app.use(cors());
7app.use(express.json()); // 解析 JSON 格式的請求
8
9// 連接到 MongoDB
10mongoose.connect('mongodb://localhost:27017/restaurant', {
11 useNewUrlParser: true,
12 useUnifiedTopology: true
13});
14
15const db = mongoose.connection;
16db.on('error', console.error.bind(console, 'MongoDB 連接錯誤:'));
17db.once('open', () => {
18 console.log('已成功連接到 MongoDB');
19});
20
21// 定義資料模型
22const catSchema = new mongoose.Schema({
23 name: String,
24 age: Number
25});
26
27const Cat = mongoose.model('Cat', catSchema);
28
29// 查看所有貓咪
30app.get('/cat', async (req, res) => {
31 try {
32 const cats = await Cat.find();
33 res.json(cats);
34 } catch (err) {
35 res.status(500).json({ message: err.message });
36 }
37});
38
39// 新增一隻貓咪
40app.post('/cat', async (req, res) => {
41 const newCat = new Cat({
42 name: req.body.name,
43 age: req.body.age
44 });
45
46 try {
47 const savedCat = await newCat.save();
48 res.status(201).json(savedCat); // 201 表示資源已創建
49 } catch (err) {
50 res.status(400).json({ message: err.message });
51 }
52});
53
54// 修改貓咪的名字
55app.put('/cat', async (req, res) => {
56 const { originalName, newName } = req.body;
57
58 try {
59 const updatedCat = await Cat.findOneAndUpdate(
60 { name: originalName },
61 { name: newName },
62 { new: true }
63 );
64 if (updatedCat) {
65 res.json(updatedCat);
66 } else {
67 res.status(404).json({ message: '找不到該名稱的貓咪' });
68 }
69 } catch (err) {
70 res.status(400).json({ message: err.message });
71 }
72});
73
74// 刪除某個名字的貓咪
75app.delete('/cat', async (req, res) => {
76 const { name } = req.body;
77
78 try {
79 const deletedCat = await Cat.findOneAndDelete({ name: name });
80 if (deletedCat) {
81 res.json({ message: `貓咪 ${name} 已成功刪除` });
82 } else {
83 res.status(404).json({ message: '找不到該名稱的貓咪' });
84 }
85 } catch (err) {
86 res.status(500).json({ message: err.message });
87 }
88});
89
90app.listen(3000, () => {
91 console.log('伺服器運行在 /');
92});
93前面的 HTTP 伺服器其實有個小問題
那就是伺服器只能被動的等待客戶端請求
如果今天有什麼事情要告訴客戶端,那也只能等客戶端來問,伺服器才做回應
所以就有了 WebSocket 這個通訊方法
基本上就是可以做到雙向通訊
SocketIO 便是一個對 WebSocket 的封裝套件,他使得程式碼的撰寫變得更簡單(就如同 express 之於 http 套件一樣)
1import express from 'express';
2import http from 'http';
3import { Server } from 'socket.io';
4
5const app = express();
6const server = http.createServer(app);
7const io = new Server(server);
8
9app.get('/', (req, res) => {
10 res.sendFile(__dirname + '/index.html');
11});
12
13io.on('connection', (socket) => {
14 console.log('一位使用者已連接');
15
16 socket.on('chat message', (msg) => {
17 console.log('訊息: ' + msg);
18 io.emit('chat message', msg);
19 });
20
21 socket.on('disconnect', () => {
22 console.log('一位使用者已離開');
23 });
24});
25
26server.listen(3000, () => {
27 console.log('伺服器運行在 ');
28});
291<!DOCTYPE html>
2<html>
3 <head>
4 <title>即時聊天</title>
5 <style>
6 ul {
7 list-style-type: none;
8 padding: 0;
9 }
10 li {
11 padding: 8px;
12 margin-bottom: 10px;
13 background-color: #f3f3f3;
14 border-radius: 4px;
15 }
16 #messages {
17 max-width: 300px;
18 margin: auto;
19 }
20 #form {
21 display: flex;
22 justify-content: center;
23 margin-top: 10px;
24 }
25 #input {
26 width: 200px;
27 padding: 10px;
28 }
29 #button {
30 padding: 10px;
31 }
32 </style>
33 </head>
34 <body>
35 <ul id="messages"></ul>
36 <form id="form" action="">
37 <input id="input" autocomplete="off" /><button id="button">送出</button>
38 </form>
39 <script src="/socket.io/socket.io.js"></script>
40 <script>
41 var socket = io();
42 var form = document.getElementById('form');
43 var input = document.getElementById('input');
44 var messages = document.getElementById('messages');
45
46 form.addEventListener('submit', function (e) {
47 e.preventDefault();
48 if (input.value) {
49 socket.emit('chat message', input.value);
50 input.value = '';
51 }
52 });
53
54 socket.on('chat message', function (msg) {
55 var item = document.createElement('li');
56 item.textContent = msg;
57 messages.appendChild(item);
58 window.scrollTo(0, document.body.scrollHeight);
59 });
60 </script>
61 </body>
62</html>
63