Angular 異步編程之(RxJs)初探

本節知識點是對【異步編程】的學習,首先我們來認識幾個概念:

  • 什麼是異步和同步?

  1. 同步的概念:執行一個方法或者功能,在沒得到結果前,其他方法不執行,一定得等當前方法執行完,纔會執行下一步驟;
  2. 異步的概念:執行一個方法或者功能,不需要等待到當前方法執行完,其他方法也可以執行;

同步比較符合我們常規思維,相對簡單,容易理解接受,異步不會按規定格式(硬編碼順序)按步驟執行,執行無序,相對複雜,當然也就不易理解接受;

  • 異步編程的常用方案有哪些?

  1. Callback 回調函數的方式獲取異步方法的數據,比如:JQuery 的 AJAX(基於XMLHttpRequest對象封裝)就實現的異步編程;
  2. Promise(ES6)對象獲取異步方法的數據;
  3. RxJs(第三方庫/Microsoft獲取異步方法的數據(ng 重度使用,比如:【HttpClient】對象);
  • 爲什麼選擇【RxJs】?

爲什麼在 ng 中會使用 RxJs,並且基於此封裝實現了【HttpClient】對象,接下來我們對上面提出的常用的異步編程的幾種方案舉例對比,由於我們整個過程中都是藉助ES中的內置函數實現分別是 setInterval() & setTimeout();

  1. setInterval() 會週期性的重複執行;
  2. setTimeout() 定時延遲執行,只執行一次;
  • CLI 創建服務【request】;
ng generate service services/request
  • 創建組件【async】;
ng generate component components/async

 在組件中引入服務並註冊聲明;

//引入服務RequestService 
import { RequestService } from '../../services/request.service';

//引入rxjs工具函數,map & filter
import { map,filter } from 'rxjs/operators'; 

//在組件的構造函數DI註冊服務request
constructor(public request:RequestService) { }

以上我們就把基礎環境準備好了,接下來我們就實現以下幾種方案:

  • Callback 回調函數方式實現異步編程;
//【request】服務中編寫
//1.Callback回調函數
getCallbackData(cb:Function):void{
  //延遲1s執行
  setTimeout(() => {
    let userName:string = '1 => 1s後執行,CallbackData => 張三';
    cb(userName);
  }, 1000); //單位ms =》 1s = 1000ms

  console.log('2 => Callback回調函數'); //此行代碼被執行
}

//在組件【async】的聲明周期函數【ngOnInit】中使用上面服務中編寫的方法
//生命週期函數,首次載入/加載或數據初始化(請求數據)使用
ngOnInit() {
  //1.callback獲取異步方法的數據
  this.request.getCallbackData((data: any) => {
    console.log(data);
  });
}
  • Promise(ES6)對象獲取異步方法的數據;
//【request】服務中編寫
//2.Promise/ES6
getPromiseData(): Promise<any>{
   return new Promise<any>((resolve)=>{
      setTimeout(() =>{
        let userName:string = '2s後執行,PromiseData => 張三';
        resolve(userName);
      }, 2000);

      console.log('2 => Promise'); //此行代碼不會被執行
   });
}

//在組件【async】的聲明周期函數【ngOnInit】中使用上面服務中編寫的方法
//生命週期函數,首次載入/加載或數據初始化(請求數據)使用
ngOnInit() {
  //2.Promise獲取異步方法的數據
  let promiseData = this.request.getPromiseData();
    promiseData.then((data)=>{
      console.log(data);
  });
}
  • RxJs(第三方庫/Microsoft)獲取異步方法的數據;
//【request】服務中編寫
//3.RxJs/Microsoft
getRxJsData(): Observable<any>{
  return new Observable<any>((observer)=>{
     setTimeout(() =>{
        let userName:string = '3s後執行,RxJsData => 張三';
        observer.next(userName);
        //observer.error('RxJsData => Error');
     }, 3000);
  });
}

//在組件【async】的聲明周期函數【ngOnInit】中使用上面服務中編寫的方法
//生命週期函數,首次載入/加載或數據初始化(請求數據)使用
ngOnInit() {
    //3.rxjs獲取異步方法的數據
    let rxjsData = this.request.getRxJsData();
    //3.1【訂閱|subscribe】
    rxjsData.subscribe((data)=>{
      console.log(data);
    }); 

    //3.2繼續上面的方式演示【取消訂閱|unsubscribe】
    let testUnsubscribe= rxjsData.subscribe((data)=>{
      console.log(data);
    }); 
    //過1s後撤回上面的方法, testUnsubscribe 接收subscribe返回的信息
    setTimeout(() =>{
      testUnsubscribe.unsubscribe(); //unsubscribe 取消訂閱
    }, 1000);
}
  • 對比 Pomise 對象和 RxJs 對象是否能執行多次方法調用;
//【request】服務中編寫
//4.Promise多次執行(沒有這個能力,只會執行一次)
getPromiseIntarvalData(): Promise<any>{
    return new Promise<any>((resolve)=>{
      setInterval(() =>{
        let userName:string = '定時輪詢,每1s執行一次,PromiseData => 張三';
        resolve(userName);
      }, 1000);
    });
}

//5.rxjs多次執行
getRxJsIntervalData(): Observable<any>{
    return new Observable<any>((observer)=>{
      setInterval(() =>{
        let userName:string = '定時輪詢,每1s執行一次,RxJsData => 張三';
        observer.next(userName);
        //observer.error('RxJsData => Error');
      }, 1000);
    });
}

//在組件【async】的聲明周期函數【ngOnInit】中使用上面服務中編寫的方法
//生命週期函數,首次載入/加載或數據初始化(請求數據)使用
ngOnInit() {
    //注意4和5演示的時候注意先註釋,方便看演示結果
    //4.Promise執行多次(沒有這個能力)
    let promiseIntervalData = this.request.getPromiseIntarvalData();
    promiseIntervalData.then((data)=>{
      console.log(data);
    });

    //5.rxjs執行多次,類似爬蟲
    let rxjsIntervalData = this.request.getRxJsIntervalData();
    rxjsIntervalData.subscribe((data)=>{
      console.log(data);
    });
}
  • RxJs 對象工具函數【map & filter】對返回的數據進行處理;
//【request】服務中編寫
//6.rxjs 工具函數【map & filter】對返回的數據進行處理
let rxjsIntervalNum = this.request.getRxJsIntervalNum();
    rxjsIntervalNum.subscribe((data)=>{
      console.log(data);
});

//在組件【async】的聲明周期函數【ngOnInit】中使用上面服務中編寫的方法
//生命週期函數,首次載入/加載或數據初始化(請求數據)使用
ngOnInit() {
    //6.rxjs 工具函數map & filter 對返回的數據進行處理
    let rxjsIntervalNum = this.request.getRxJsIntervalNum();
    rxjsIntervalNum.subscribe((data)=>{
      console.log(data);
    });

    /*
    //filter單個使用
    rxjsIntervalNum.pipe(  //pipe 管道
      //過濾count爲偶數的數據
      filter((value) => {
        if (value % 2 ==0) {
          return true;
        }
      })
    ).subscribe((data)=>{
      console.log(data);
    });
    */
    
    /*
    //map單個使用
    rxjsIntervalNum.pipe(  //pipe 管道
      //對結果數據處理後再返回
      map((value) => {
        if (value % 2 ==0) {
          return value * value;
        }
      })
    ).subscribe((data)=>{
      console.log(data);
    });
    */

    //map & filter 聯合使用
    rxjsIntervalNum.pipe(  //pipe 管道,可以有序的打包多個方法一併執行
      //1.先按條件過濾
      filter((value) => {
        if (value % 2 ==0) {
          return true;
        }
      }),
      //2.對過濾後的數據進行處理後再返回
      map((value) => {
        if (value % 2 ==0) {
          return value * value;
        }
      })
    ).subscribe((data)=>{
      console.log(data);
    });
}
  • Promise(ES6)和 RxJs 對比:
  1. Promise 通過【then】獲取異步方法數據,RxJs通過【subscribe】獲取異步方法數據;
  2. Promise執行方法後無法撤銷,而RxJs可以實現訂閱【subscribe】和取消訂閱【unsubscribe】;
  3. Promise只能執行一次(沒有這個能力),RxJs可以執行多次(類似定向任務/輪詢獲取數據/爬蟲);
  4. RxJs 可以延遲執行;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章