# Web企業運算_Week10_許家維 ### 學習清單 1.上課內容觀念複習(callback,promise...etc) 2.履歷修改 3.技術文件閱讀 學習資料 Promise 教學文件 : https://developers.google.com/web/fundamentals/primers/promises?fbclid=IwAR2yQZo71z1ACmTU8zG7XvHo7PesmAdMT0mSaoIhDcofOegNR0qgPfBYfYo 本篇文章連結 : https://hackmd.io/kInBHUu1TZKyt-W5qXu3Gw?both ### Code app.module.ts ``` import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; <!-- 使用httpclient模組 --> import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ <!-- import模組 --> BrowserModule, HttpClientModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ``` app.component.ts ``` import { Component } from '@angular/core'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'HttpApp'; data: any; // inject object constructor(private http:HttpClient){ <!-- 抓取資料 --> this.http.get('http://jsonplaceholder.typicode.com/posts').toPromise() <!-- 渲染出資料 --> .then(data=>{console.log(data); this.data = data;}) <!-- 若錯誤 --> .catch(err=> console.log(err)); } } ``` app.component.html ``` <h1>抓取網路Api資料</h1> <!-- 遍歷所有的data 給一個變數d --> <ul *ngFor = "let d of data"> <!-- 依據資料格式顯示出來 --> <li>使用者序號:{{d.userId}}</li> <li>標題:{{d.title}}</li> <li>內容:{{d.body}}</li> </ul> ``` 稍做一點美觀後... ![](https://i.imgur.com/iWcYc16.png) 資料成功抓進來了 !! ### 成果 #### Asynchronous Programming 非同步程式設計 **1. CallBack 回調** 是一個可以作為傳入參數的函式,用於在目前的函式呼叫執行最後移交控制權,而不使用函式回傳值的方式。 直接風格 ``` function func(x) { return x } ``` Callback寫法 ``` function func(x, cb) { cb(x) } ``` 異步回調函式種類通常有 : * 使用計時器(timer)函式: setTimeout, setInterval * 特殊的函式: nextTick, setImmediate * 執行I/O: 監聽網路、資料庫查詢或讀寫外部資源 * 訂閱事件 * 範例 ``` function aFunc(value, callback){ callback(value) } <!-- 即使設定為0ms,裡面的回調函式並不是立即執行,而是會暫緩(延時)執行 --> function bFunc(value, callback){ setTimeout(callback, 0, value) } function cb1(value){ console.log(value) } function cb2(value){ console.log(value) } function cb3(value){ console.log(value) } function cb4(value){ console.log(value) } aFunc(1, cb1) bFunc(2, cb2) aFunc(3, cb3) bFunc(4, cb4) <!-- 執行順序 1>3>2>4 --> ``` **2. Promise** Why Promise ? JavaScript 是屬於同步的程式語言,因此一次僅能做一件事情,但遇到非同步的事件時,就會將非同步的事件移動到程式碼的最後方,等到所有的原始碼運行完以後才會執行非同步的事件。 * 概念圖解 ![](https://i.imgur.com/nND8fNR.png) * **Promise 一個特點在於 then、catch 都可以使用鏈接的方式不斷的進行下一個任務,在此範例中我們修改 Promise 的結果,改成傳入 0 則會調用 reject,其它數值則會調用 resolve** ``` function promise(num) { return new Promise((resolve, reject) => { num ? resolve(`${num}, 成功`) : reject('失敗'); }); } ``` Promise API * all -> 多個 Promise 行為同時執行,全部完成後統一回傳 * race -> 多個 Promise 同時執行,但僅回傳單一結果 * Promise.reject, Promise.resolve -> 直接定義 Promise 物件已經完成的狀態(resolve, reject),與 new Promise 一樣會產生一個新的 Promise 物件,但其結果是已經確定的 **3. Observable 可觀察物件 based on Angular** 支援在應用中的發佈者和訂閱者之間傳遞訊息。 在需要進行事件處理、非同步程式設計和處理多個值的時候,可觀察物件相對其它技術有著顯著的優點。 基本用法 **要執行所建立的可觀察物件,並開始從中接收通知,你就要呼叫它的 subscribe() 方法,並傳入一個觀察者(observer)。 這是一個 JavaScript 物件,它定義了你收到的這些訊息的處理器(handler)** 下面的例子會建立並訂閱一個簡單的可觀察物件,它的觀察者會把接收到的訊息記錄到控制檯中 ``` // Create simple observable that emits three values const myObservable = of(1, 2, 3); // Create observer object const myObserver = { <!-- next:用來處理每個送達值。在開始執行後可能執行零次或多次 --> next: x => console.log('Observer got a next value: ' + x), <!-- error:用來處理錯誤通知。錯誤會中斷這個可觀察物件實例的執行過程 --> error: err => console.error('Observer got an error: ' + err), <!-- complete:處理執行完畢通知。當執行完畢後,這些值就會繼續傳給下一個處理器 --> complete: () => console.log('Observer got a complete notification'), }; // Execute with the observer object myObservable.subscribe(myObserver); // Logs: // Observer got a next value: 1 // Observer got a next value: 2 // Observer got a next value: 3 // Observer got a complete notification ``` **4. RxJS 函式庫** RxJS(響應式擴充套件的 JavaScript 版)是一個使用可觀察物件進行響應式程式設計的函式庫,它讓組合非同步程式碼和基於回調(Callback)的程式碼變得更簡單 **RxJS 提供了一種對 Observable 型別的實現**,直到 Observable 成為了 JavaScript 語言的一部分並且瀏覽器支援它之前,它都是必要的。這個函式庫還提供了一些工具函式,用於建立和使用可觀察物件。這些工具函式可用於: * 把現有的非同步程式碼轉換成可觀察物件 * 迭代流中的各個值 * 把這些值對映成其它型別 * 對流進行過濾 * 組合多個流 RxJS 提供了一些用來建立可觀察物件的函式。這些函式可以簡化根據某些東西建立可觀察物件的過程,比如事件、定時器、承諾等等。比如: ``` <!-- 利用rx.js 建立一個promise 的可觀察物件 --> import { from } from 'rxjs'; // Create an Observable out of a promise const data = from(fetch('/api/endpoint')); // Subscribe to begin listening for async result data.subscribe({ next(response) { console.log(response); }, error(err) { console.error('Error: ' + err); }, complete() { console.log('Completed'); } }); ``` **5. Async & Await** 在 ES7 裡頭 async 的本質是 promise 的語法糖,**只要 function 標記為 async,就表示裡頭可以撰寫 await 的同步語法**。await 顧名思義就是「等待」,它會確保一個 promise 物件都解決 ( resolve ) 或出錯 ( reject ) 後才會進行下一步,當 async function 的內容全都結束後,會返回一個 promise,這表示後方可以使用.then語法來做連接 ``` ~async function { // ~ 開頭表示直接執行這個 function,結尾有 () const delay = (s) => { return new Promise(function(resolve){ // 回傳一個 promise setTimeout(resolve,s); // 等待多少秒之後 resolve() }); }; console.log(1); // 顯示 1 await delay(1000); // 延遲ㄧ秒 console.log(2); // 顯示 2 await delay(2000); // 延遲二秒 console.log(3); // 顯示 3 }(); ``` **6. HttpClient** 大多數前端應用都需要透過 HTTP 協議與後端伺服器通訊。現代瀏覽器支援使用兩種不同的 API 發起 HTTP 請求:**XMLHttpRequest 介面和 fetch() API。** @angular/common/http 中的 HttpClient 類別為 Angular 應用程式提供了一個簡化的 API 來實現 HTTP 客戶端功能。它基於瀏覽器提供的 XMLHttpRequest 介面 引入語法 : ```import { HttpClientModule } from '@angular/common/http'; ``` 再來,將 HttpClient 注入到應用類別 ``` @Injectable() export class ConfigService { <!-- 建構子,定義 Property 的初始值 --> constructor(private http: HttpClient) { } } ``` ### 心得 這週首先複習了上上周學的Promise概念,透過練習又學了一些技巧。也把callback、es7的async與await等觀念了解的更加清楚。未來會多看一些非同步處理的實務範例,未來希望能夠運用於專案上。Angular的架構,透過許多個禮拜的練習,也漸漸的熟悉起來,或許有時間可以自己製作一個side project吧!另外這週也上了angular的httpcilent模組,能夠透過網路上的API抓取資料並顯示在螢幕上。這部分在VUE有接觸一些,但還不是特別熟悉,會再努力練習這部分(包含資料的預先整理、清洗等...)