Pmroise , async_await …
- call back
補充:https://cythilya.github.io/2018/10/30/callback/ - Synchronous vs Asynchronous
顧客:阻塞(憨厚) vs 非阻塞(變通) polling
老闆:同步(臭跩) vs 非同步(親切)
ex:公司報到+銀行開戶
避免過度阻塞
polling
longpolling
streaming (websocket)
補充:
https://blog.niclin.tw/2017/10/28/%E7%8D%B2%E5%BE%97%E5%AF%A6%E6%99%82%E6%9B%B4%E6%96%B0%E7%9A%84%E6%96%B9%E6%B3%95polling-comet-long-polling-websocket/
https://blog.gtwang.org/web-development/websocket-protocol/
補充:
https://johlmike.wordpress.com/2016/07/08/%E5%90%8C%E6%AD%A5synchronous%E3%80%81%E7%95%B0%E6%AD%A5asynchronous%E3%80%81%E9%98%BB%E5%A1%9Eblock%E3%80%81%E9%9D%9E%E9%98%BB%E5%A1%9Enon-block/
阻塞與非阻塞主要是描述請求在等待結果時的狀態
同步與異步主要是描述回傳的聯絡方式
非同步有
1.setInterval setTimeout 2.一般的 eventhandler
3.server 的呼叫
- 佇列、堆疊、事件循環
佇列(Queue):先進先出 ex:排隊、jQuery 動畫
堆疊(Stack):後進先出 ex:河內塔
事件循環(Event Loop):從佇列提取到堆疊執行
補充:
https://pjchender.blogspot.com/2017/08/javascript-learn-event-loop-stack-queue.html
非同步處理:主流程處理完後處理
Stack 不清空,Queue 是無法往下做的
補充:
https://ithelp.ithome.com.tw/articles/10200054?sc=iThelpR
loupe:
http://latentflip.com/loupe/
1 | function A(){ |
1 | log('=====start=====') |
+new Date()
等同於 new Date().getTime()
不要用 Timer 控流程,時間不準
1 | "MY_ROOM": { |
- Promise
(1) 可以做同步組合
(2) Queue 在不同瀏覽器可能會有不同表現
1 | const promise = (time, msg) => { |
promise:等到允許授權才能往下走
then 須等到 resolve
1 | // 觀戰重點4: 執行順序,將同步非同步變成依序執行 |
1 | log("===== Start ====="); |
1 | setTimeout(() => { |
finally
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Control_flow_and_error_handling
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally
1 | function f() { |
後進先出範例
1 | 後進先出; |
- Pmroise.all vs Promise.race
all:全部一起做,時間最長的
race:只取最快回來的資料
1 | Promise.all([ |
- Generator
function*()
會自動產生 return
建議為每個 function 做適當的 return 值
Generaor+Promise 的範例(async await 的前身)
1 | let gen = genFn(); |
補充:所有 function 都應該有 return,沒有 return 他就是 undefined
如果是事件觸發,那 return 值就會沒人會使用到
- async_await
async => 非同步 , await => 等
async await => 等非同步
補充:
7.1 await 只能存在 async function 裡面
7.2 await 必須等非同步(必須等非同步(promise))
重要:先讓 promise 做完(同步),再一起 await,不要一邊 promise,一邊 await,因為會讓同步的 promise 的同步做成非同步的
1 | (async function() { |
1 | (async function() { |
async function 裡面有 await
await 等 async function
await 等 promise
- async_array
同一個作用域裡,await 才會互等
1 | (async function() { |
補充:
大部分有用的 this 時候都會用 function,大部分第二層就會用箭頭函式,setTimeout,就會往外找,找到上一層的對象(document)
1 | document.addEventListener("xxx", function() { |
- API
(1) 販賣機
NG-1 吃錢
NG-2 給錯東西
=> 給正確的東西
(2) 拉麵販賣機
打對的網址(按對的按鈕)
給正確的查詢
回正確的資料(固定有規範的輸入與輸出)
- JSON
JavaScript Object Notation
最上層建議:物件
Restful API : Representational State Transfer
Read:GET 讀取紀錄
Create:POST 新增紀錄
Update:PUT/PATCH 修改紀錄
Delete:DELETE 刪除紀錄
Http Status Code:
//ok => then
2xx:這是您要的東西
3xx:請稍後為您轉接
//error => catch
4xx:請查明後再撥
5xx:嘟~嘟~嘟~
TCP 三次握手與四次揮手
C:Client S:Server
傳輸前:
三次握手(確認雙方都在)
1 C:安安,你好!住哪?給虧嗎? => 尋找目標 Server
2 S:台北,28 => Server 回應
3 C:好巧喔!我也住台北 => Client 也回應
雙方連上線開始傳輸
離開前:
四次揮手
1 C:我要去洗澡了 => 我要結束了(C)
2 S:等一下 => 確認是否還有未傳完(S)
3 S:我去洗澡 (雙重攻擊) => 傳完我要結束了(S)
4 C:你就去吧 => 你可以結束了(C)
此時 Server 斷線,等待兩秒確定斷線,Client 也斷線
DoS 攻擊:大量請求,使 Server 被打到癱瘓,無法正常服務
SQL VS NOSQL
SQL:關聯,查詢資料需要透過多個資料表查詢,較費時
資料分散,資料較小 ( 時間換空間 )
NOSQL:需要資料直接拿整包,不需要組合,較快
資料較多份,資料較大 ( 空間換時間 )
( Not Only SQL )
cookie vs session
Token:令牌/通行證
Storage:都存在本機
Local Storage:沒有時效性,連線不會傳,不刪他不會被刪除 (長時間暫存)
Session Storage:跟著 Tag(分頁),關閉就刪除(session 連線結束 會被清掉),存在 SERVER 端會占用 SERVER 端的資源,單次連線的暫存 儲存在 server 端(暫存檔)
cookie:存在本機,使用者可以刪除,有期限的(可設計過期時間),SERVER 在每次連線的時候會自動綁定和傳輸(目的:隨使想取用都可以做檢查),不適手動自己加的東西 儲存在 user 端 (短期),不建議前端操作 cookie
補充:TOKEN 都會放在 cookie 為主
Http Only:程式不能刪
session:連線階段的操作,存在 server 端,使用者不能刪除
PUT vs PATCH
PUT:傳整包,實務上後端某些欄位會鎖住(例如:ID),相信你傳
PATCH:傳部分修改資料
理論上如此,但實作還是要看後端作法
範例 9
- 讀取資料 (讀取 api 是非同步,所以呼叫時,必須加 await,因為必須等非同步完成才 render,不然 render 時回沒有資料 render,ex:await xxx()),await 是一種等的概念,render(同步)必須等 await loadData()的概念
- 渲染畫面
- 使用者功能
reduce:組合技
1 | const input = $(this) |
location.reload():刷新畫面
讀取資料 => 渲染畫面 => 使用者功能
可以考慮重構成下面:
讀取表單資料(users) => 渲染表單 => 表單功能
讀取列表資料(posts) => 渲染列表 => 列表功能
補充:
form 的好工具
1 | const input = $(this).serializeArray(); |
JSONP
JSON with Padding
解決跨域問題
物件導向
封裝:分類,然後包起來(資料 attribute+功能 Methods)
繼承:爸爸有房子,我就有房子
SOLLID
S:做好分類 (單一職責(Single Responsibility Principle
O:開放擴充 封閉修改 (開放封閉(Open-Closed Principle
L:小孩可以代替爸爸 爸爸不能代替小孩 (里氏替換(Liskov Substitution Principle
L:只給部分功能 (最小知識(Least Knowledge Principle
I:不受其他介面影響 (介面隔離(Interface Segregation Principle
D:避免小孩影響到爸爸 (依賴反轉(Dependency Inversion Principle
物件建議
- 判斷 this 再使用(有 new 就是你創物件本身,不然就是指向 window(全域))
1 | const Creature = function(name, sex){ |
- function 如果是做一樣事情,建議拉到 proto 做,不然在 new 的時候會多產生
- 公有與私有
4.defineProperty 非常重要!! 與陣列 reduce 一樣重要
defineProperty 的功能是把一個屬性轉變成 function(並分別有讀和取的功能)
改成 function 的好處,他可以回傳 callback,ex: 假設有人改你的資料,就會回傳,但變數卻無法
1 | let _age = 30; |
1 | //defineProperties的寫法 |
prototype 與proto的分別
就是物件生成前後(ex: new Creature),之前
Creature.prototype.intro = function(){
}
new 出來之後只能讀到proto,讀 prototype 會有一些問題
X 全域變數
X 浮點數計算
X with 與 eval
X 強制轉型的雙等號
X 無所不在的宣告
X 無區塊的敘述式
X 函式敘述與運算
X 類型的包裝與 New
X 隨意換行與分號
X 加號運算子
X continue
X switch 穿越
X 分散的回傳值
X 太早做過度縮寫
1 | let a = "A"; |
閉包
咖哩化
模式
工廠模式 (Factory)
主力:產東西
EX: Object
策略模式 (Strategy)
主力:對應東西
策略表(Map 表)
外觀模式 (Facade)
一個 function 包很多功能
EX:點青椒炒牛肉 => 處理青椒/處理牛肉/炒都交給廚師處理
點餐的人不需要知道這些
觀察者模式
觀察者模式 : 透過第三者溝通 EX:事件
MV*
Model 資料邏輯
View 畫面層
C:畫面對 Model 監聽
P:畫面透過 Present 偵聽?
第三天
prototype
- People.prototype = Creature.prototype
直接賦值 prototype
問題: 原本方法被取代 - People.prototype = new Creature()
問題: 有自己及父親的屬性,本身屬性移除就變成父親的屬性
方法也會不見(多額外屬性) - 繼承方法
1 | Function.prototype.extend = function(parent) { |
protp : 實體化使用
prototype : 未實體化
1 | const Alex = function() {}; |
作業 : alex.lvUp(‘People’)
1 | const People = function(name) { |
與下面差異相同
1 | function A() { |
class
- class 關鍵字
- construtor 初始化
- static function
//TODO 待補
複製 obj
- obj1 = {…obj}
- obj2 = Object.assign({},obj)
- obj3 = JSON.parse(JSON.stringigy(obj))
- obj4 = {}
- Object.create()
複製 function
閉包
1 | function copyFunction(fun) { |
MVC VS MVP
- MVC
V -event-> C -> M -> V - MVP
V <-> P <-> M->-> - MVVM
V <-> VM <-> M->->
MVC
- 主程式(拉近三個架構 App
- 另外三隻檔案( View/Mode/Controller
- Observer
Alex 開發順序(參考)
- 先做基礎架構(App 主程式)
1-1 import MVC
1-2 開三支檔案
1-3 做關係(new 出來
View 需要認識 Model
Controller 要認識 Model 跟 View
1 | const M = new Model(); |
Model (資料邏輯)
增加/讀取/選擇/刪除(事件)
做完後打事件出去
盡量不要動畫面View (畫面邏輯:畫面偵聽/資料變動)
3-1 記資料
3-2 匯入 jQuery (import \$ from ‘jquery’
盡量不要動資料
補充 call/apply/bind
與 function 的 this 操作有關
1 | let A = { |
show 改變畫面
MVC 架構中,View 不能自己改畫面,要通知讓後面去改
這邊採用畫面全部重劃較耗效能,可以嘗試修改不要整個畫面重畫
- Controller (牽手=>控制 Model)
TODO:可以練習 switchHandler
Singleton
單例模式 : 閉包
判斷如果產生過,就用之前產生的,沒產生過再產生新的
概念類似
1 | let a = { count: 0 }; |
練習:
- 繼承練習
- MVC 架構修正 View 的 switch 事件
第三天下午
問題討論
1 | var out = 25, |
1 | let a = (1, 2); |
DL DT DD
DL=>Definition List
DT=>Definition Term
DD=>Definition Description
Observer 觀察者模式
電視/收音機無時無刻都在播放,但你有沒有去看/聽 (觀察)
決定會部會有回應
結構:1 個持續播放,1 個監聽者
功能:解耦
耦合
我在你也在,我死你也死
1 | const Observer = function(host) { |
改成下面,不容易在 ob 內部發生 b1/b2 錯誤
//TODO 待補
1 | ``` |
1 | loading = true; |