### GDSC NYUST x 資訊創客社
<br>
### 軟體開發工具入門讀書會
#### JS & RESTful API課程
<br>
#### 2023/10/30 ( Mon ) 19:00 - 21:00
#### 講師:蘇祐民
#### 本次課程影片:
<img src="" height="200px">
---
## JS & RESTful API課程
*YoMin Su*
---
## 課程簡介
----
### 簡單的說
1. 了解 JS 與 TS
2. 了解RESTful API的概念
3. 實際在JS或TS上使用RESTful API
----
### 複雜點講
- 對JS與TS的基本認識
- 學習變數宣告、陣列與物件的使用
- 函數宣告
- JS/TS的物件導向
- 非同步概念
- RESTful API基本概念
- HTTP Method說明
- API的CRUD操作
- 透過JS進行CRUD操作
- 介紹Fetch用法
- 介紹Axios套件
---
## Part 1
### JS / TS
----
### What is JS/TS ?
是一個在1995年隨著瀏覽器一起出現的程式語言,在當時,被當作輔助HTML的一種『膠水語言』,隨著時間的推進,慢慢地出現了豐富的生態系與各種方便好用的套件,也才出現了現今網頁的用JS包起HTML的設計方法!

----
### JS / TS 哪裡不同 ?
TypeScript是JavaScript的嚴格語法超集,出現的原因也很明確,由於JS本身設計上的彈性,使我們在開發時,無法明確知道每個方法本身需要的參數類型與預期的回傳結果,這樣的狀況讓微軟的開發者在設計上,遇到了相當大的困擾,也因此,才會出現TS這個結果,其本身仍是將程式碼編譯回JS,但透過『.d.ts』這樣的型別定義,就能讓開發時減少許多麻煩!
----
### 簡單解釋
1. 微軟想寫JS
2. 發現JS沒有型別
3. 很難把程式規模寫大
4. 決定改進JS,於是有了TS
5. TS編譯後,就可透過JS運作
6. 不強迫將型別合併,可透過『.d.ts』定義
----
### 變數宣告時間
<table>
<tr>
<td> JavaScript </td> <td> TypeScript </td>
</tr>
<tr>
<td>
```javascript=
let x = 0;
var y = "Hi";
const z = {}
```
</td>
<td>
```typescript=
interface IPerson {
name: string;
age: number;
}
let x: number = 0;
var y: string = "Hi";
const z: IPerson = {};
```
</td>
</tr>
</table>
----
### 資料型別(TS)
| Type | Description |
| ------------- | ---------------- |
| number | 數字(整數、小數) |
| string | 不定長度字串 |
| boolean | 布林值 |
| \<type\>[] | 陣列宣告 |
| Array\<type\> | 陣列宣告2 |
| any | 任意 |
----
### 陣列
<table>
<tr>
<td>JavaScript</td>
<td>
```javascript=
let x = [123, "abc", {}];
```
</td>
</tr>
<tr>
<td>TypeScript</td>
<td>
```typescript=
let x: number[] = [123, 456, 789];
let y: Array<string> = ["abc", "def"];
let z: any[] = [123, "abc", {}];
```
</td>
</tr>
</table>
----
### 物件
<table>
<tr>
<td>JavaScript</td>
<td>
```javascript=
let x = {
name: "YoMin",
age: 20,
graduate: true
};
```
</td>
</tr>
<tr>
<td>TypeScript</td>
<td>
```typescript=
let x: {name: string, age: number, graduate: boolean} = {
name: "YoMin",
age: 20,
graudate: true
};
```
</td>
</tr>
</table>
----
### 物件型別(TS)
```typescript=
//Method 1
type Person = {
name: string;
age: number;
}
//Method 2
interface Person {
name: string;
age: number;
}
```
----
### 函數 / 方法
JavaScript:
```javascript=
//沒有return的話,預設會是undefined
function hello(name) {
console.log("Hi", name);
}
const hi = (name) => {
console.log("Hello", name);
}
```
----
### 函數 / 方法
TypeScript:
```typescript=
//沒有return的話,預設會是undefined
function hello(name: string): void {
console.log("Hi", name);
}
const hi = (name: string): boolean => {
console.log("Hello", name);
return true;
}
```
----
### 呼叫函數
JavaScript:
```javascript=
hello("YoMin");
//預期輸出 => Hi YoMin
hi("Kent");
//預期輸出 => Hello Kent
```
----
### 呼叫函數
TypeScript:
```typescript=
console.log(hello("YoMin"))
//預期輸出1 => Hi YoMin
//預期輸出2 => undefined
console.log(hi("Kent"))
//預期輸出1 => Hello Kent
//預期輸出2 => true
```
----
### 特別的函數用法
1. Callback時使用的匿名函數
```javascript=
app.get('/', function (req, res, next) {
res.send("Hi!");
});
```
2. 箭頭函數
```javascript=
const method = () => {
console.log("I'm Here!");
}
```
---
## Part 1
### OOP
----
### 首先講講JS原生怎麼搞
```javascript=
function Person(name, age) {
this.name = name;
this.age = age;
const getName = () => this.name;
const getAge = () => this.age;
const setName = (name) => {
this.name = name;
}
const setAge = (age) => {
this.age = age;
}
return {
getName,
getAge,
setName,
setAge
}
}
```
----
### 接著看看TypeScript可以怎麼用
```typescript=
class Person {
private name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
function hi(): void {
console.log("Hi", this.name);
}
function howOld(): void {
console.log(`I'm ${this.age} years old!`);
}
function setName(name: string): void {
this.name = name;
}
function setAge(age: number): void {
this.age = age;
}
}
```
----
### 使用(JS)
```javascript=
let yomin = Person("YoMin", 20);
yomin.getName();
yomin.getAge();
yomin.setAge(30);
yomin.getAge();
```
----
### 使用(TS)
```typescript=
let yomin = new Person("YoMin", 20);
yomin.getName();
yomin.getAge();
yomin.setAge(30);
yomin.getAge();
```
----
### 多型(TS)
```typescript=
abstract class Animal {
private name: string;
private type: string;
constructor(name: string, type: string) {
this.name = name;
this.type = type;
}
abstract public eat();
}
class Dog extends Animal {
constructor(name: string, type: string) {
super(name, type);
}
public eat() {
console.log("Dog Eat!");
}
}
class Cat extends Animal {
constructor(name: string, type: string) {
super(name, type);
}
public eat() {
console.log("Cat Eat!");
}
}
```
----
### 存取修飾符
- Public
- 公開,所有人都可以用
- Private
- 不公開,只有自己可以用
- Protected
- 半公開,只讓自己的孩子可以用
----
### 存取修飾符 宣告
```typescript=
public name: string = "YoMin";
private age: number = 20;
protected sex: string = "Male";
```
---
## Part 1
### 非同步
----
### 入門
首先要來推薦影片,非常好用的一部
<iframe width="800" height="450" src="https://www.youtube.com/embed/8aGhZQkoFbQ?si=guE-3h3UmjYs0L0T" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
----
### 非同步的基本用法
```javascript=
axios.get("/").then((res) => {
console.log(res);
})
```
這是透過Callback的方式處理的,當方法本身是非同步時,會回傳一個Promise物件,本身會有幾種狀態,讓我們來簡單說明
----
### Promise 物件
本身會涵蓋三種狀態,狀態說明如下:
- Pending (處理中)
- 正在執行,還沒有得到結果
- Fulfilled (成功)
- 執行成功,正常拿到結果,可以使用
- Rejected (拒絕)
- 執行失敗,過程發生錯誤,需處理錯誤
----
### 當成功的時候
```javascript=
.then((<parameter>) => {
//Something here.
})
```
成功的結果會作為『匿名箭頭函數的參數』被傳遞進去,而後續的程式碼,將寫在該函數的作用域中
----
### 當失敗的時候
```javascript=
.catch((err) => {
console.log(err);
//Something here
})
```
失敗的結果一樣會作為函數的參數被傳遞進去,通常會將其顯示在終端上,方便進行除錯。
----
### 範例用法
```javascript=
axios.get("/")
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
```
----
### Callback Hell (波動拳)

----
### 另一種使用非同步的語法糖
- async
- 標記為非同步,會在背境繼續執行
- await
- 等待,讓程式等待執行結果出來
----
### async / await 實作
```javascript=
async hi() {
let result = await someMethod();
console.log(result);
}
```
如果今天是透過TS進行設計的話,沒有正確處理Promise物件時,TS的解析器會直接跳出錯誤,避免不正確的結果被繼續使用下去!
---
## Part 2
### RESTful API 基本概念
----
### 什麼是RESTful API ?
- 是一種設計風格,而非是標準
- 通常是與HTTP、URI、XML及HTML一起使用
- 資源是由URI來指定
- 對資源的操作包括取得、建立、修改和刪除,剛好能對應HTTP提供的GET、POST、PUT(PATCH)和DELETE方法。
----
### RESTful的特色
- Uniform Interface:統一介面。
- Stateless:無狀態。
- Cacheable:可快取。
- Client-Server:客戶伺服器分離模式,任何一個客戶端與伺服器都是可替換的。
- Layered System:分層的系統,客戶端不知道他聯絡的是不是最終伺服器。
> 源自Wikipedia
----
### 來看看URL的每個部分

----
### CRUD 操作
| Methods | Description |
| ---------- | ----------- |
| GET | 取得資料 |
| POST | 新增資料 |
| PUT(PATCH) | 更新資料 |
| DELETE | 刪除資料 |
---
## Part 3
### 實際操作
----
### 環境準備
1. 可以使用你的瀏覽器(限制較多)
2. 或是使用Node.js
安裝指令:
```bash=
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=20
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
```
----
### 原生的Fetch
```javascript=
fetch("https://www.google.com/")
.then((res) => {
console.log(res);
});
```
----
### 拿到的回應

----
### 來看看內容
```javascript=
fetch("https://www.google.com/")
.then((res) => {
return res.text();
})
.then((data) => {
console.log(data);
});
```
----
### 全都是HTML呢~

----
### 如果是JSON呢?
```javascript=
fetch("https://www.google.com/")
.then((res) => {
return res.json();
})
.then((data) => {
console.log(data);
});
```
----
### 出現了錯誤!
因為在對Google請求後,回應的是網站內容,不是JSON資料

----
### 改用中央氣象署看看
請註冊他們的帳號,並申請一組自己的API授權碼

----
### 課程範例用的路由
> 點我進去:[API說明文件](https://opendata.cwa.gov.tw/dist/opendata-swagger.html?urls.primaryName=openAPI#/%E9%A0%90%E5%A0%B1/get_v1_rest_datastore_F_D0047_091)

----
### 複製到Node.js嘗試看看

----
### 如果想使用回傳內的資料呢?

----
### 有關fetch的補充說明
- [Fetch MDN](https://developer.mozilla.org/zh-TW/docs/Web/API/Fetch_API)
- [AJAX 與 Fetch API](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/ajax_fetch.html)
----
### 接著來看看Axios套件
----
### 安裝Axios
```bash=
mkdir axios_test
cd axios_test
yarn init #全部預設即可
yarn add axios
node
```
----
### 來嘗試看看剛剛的範例
```javascript=
let axios = require('axios');
axios.get('https://www.google.com/')
.then((res) => console.log(res));
```

----
### 如果要取得資料的話
```javascript=
axios.get('https://www.google.com/')
.then((res) => console.log(res.data));
```

----
### Axios 與 Fetch 差在哪裡?
- 簡化性: axios提供了一個簡易的API,使HTTP請求更容易使用,並自動處理了許多常見的請求和回應工作。
- 攔截器: axios可以使用攔截器在請求和回應的不同階段執行自定義邏輯,這對於添加驗證、日誌記錄等非常有用。
- 預設設定: 您可以設定Global的預設設置,像是基本URL、超時(Timeout)設定等,以減少重複性工作。
- 自動JSON解析: axios會自動解析JSON回應,而使用Fetch需要手動處理。
---
## Part 4
### Q&A + 回家作業
----
### 有任何問題嗎?
----
### 回家作業
> TBD
----
### 學習資源
- [TypeScript 新手指南](https://willh.gitbook.io/typescript-tutorial/)
- [MDN Fetch API](https://developer.mozilla.org/zh-TW/docs/Web/API/Fetch_API)
- [GitHub: axios](https://github.com/axios/axios)
---
# BYE

{"title":"JS & Restful API課程","description":"YoMin Su","slideOptions":"{\"transition\":\"concave\",\"allottedMinutes\":100}","contributors":"[{\"id\":\"f8142aa2-66aa-4867-821d-2f1ffff7a7ba\",\"add\":10581,\"del\":28}]"}