響應式編程思維藝術】 (5)Angular中Rxjs的應用示例

      網友投稿 894 2022-05-29

      本文是【Rxjs 響應式編程-第四章 構建完整的Web應用程序】這篇文章的學習筆記。

      示例代碼托管在:http://www.github.com/dashnowords/blogs

      博客園地址:《大史住在大前端》原創博文目錄

      華為云社區地址:【你要的前端打怪升級指南】

      【響應式編程的思維藝術】 (5)Angular中Rxjs的應用示例一. 劃重點二. Angular應用中的Http請求三. 使用Rxjs構建Http請求結果的處理管道3.1 基本示例3.2 常見的操作符四. 冷熱Observable的兩種典型場景4.1 shareReplay與請求緩存4.2 share與異步管道五. 一點建議

      一. 劃重點

      RxJS-DOM

      原文示例中使用這個庫進行DOM操作,筆者看了一下github倉庫,400多星,而且相關的資料很少,所以建議理解思路即可,至于生產環境的使用還是三思吧。開發中Rxjs幾乎默認是和Angular技術棧綁定在一起的,筆者最近正在使用ionic3進行開發,本篇將對基本使用方法進行演示。

      冷熱Observable

      冷Observable從被訂閱時就發出整個值序列

      熱Observable無論是否被訂閱都會發出值,機制類似于javascript事件。

      涉及的運算符

      bufferWithTime(time:number)-每隔指定時間將流中的數據以數組形式推送出去。

      pluck(prop:string)- 操作符,提取對象屬性值,是一個柯里化后的函數,只接受一個參數。

      二. Angular應用中的Http請求

      Angular應用中基本HTTP請求的方式:

      import { Injectable } from '@angular/core';

      import { Observable, of } from 'rxjs';

      import { MessageService } from './message.service';//某個自定義的服務

      import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';

      @Injectable({

      providedIn: 'root'

      })

      export class HeroService {

      private localhost = 'http://localhost:3001';

      private all_hero_api = this.localhost + '/hero/all';//查詢所有英雄

      private query_hero_api = this.localhost + '/hero/query';//查詢指定英雄

      constructor(private http:HttpClient) {

      }

      /*一般get請求*/

      getHeroes(): Observable>{

      return this.http.get(this.all_hero_api,{observe:'response'});

      }

      /*帶參數的get請求*/

      getHero(id: number): Observable>{

      let params = new HttpParams();

      params.set('id', id+'');

      return this.http.get(this.query_hero_api,{params:params,observe:'response'});

      }

      /*帶請求體的post請求,any可以自定義響應體格式*/

      createHero(newhero: object): Observable>{

      return this.http.post>(this.create_hero_api,{data:newhero},{observe:'response'});

      }

      }

      在express中寫一些用于測試的虛擬數據:

      var express = require('express');

      var router = express.Router();

      /* GET home page. */

      router.get('/all', function(req, res, next) {

      let heroes = [{

      index:1,

      name:'Thor',

      hero:'God of Thunder'

      },{

      index:2,

      name:'Tony',

      hero:'Iron Man'

      },{

      index:3,

      name:'Natasha',

      hero:'Black Widow'

      }]

      res.send({

      data:heroes,

      result:true

      })

      });

      /* GET home page. */

      router.get('/query', function(req, res, next) {

      console.log(req.query);

      let hero= {

      index:4,

      name:'Steve',

      hero:'Captain America'

      }

      res.send({

      data:hero,

      result:true

      })

      });

      /* GET home page. */

      router.post('/create', function(req, res, next) {

      console.log(req.body);

      let newhero = {

      index:5,

      name:req.body.name,

      hero:'New Hero'

      }

      res.send({

      data:newhero,

      result:true

      })

      });

      module.exports = router;

      在組件中調用上面定義的方法:

      sendGet(){

      this.heroService.getHeroes().subscribe(resp=>{

      console.log('響應信息:',resp);

      console.log('響應體:',resp.body['data']);

      })

      }

      sendQuery(){

      this.heroService.getHero(1).subscribe(resp=>{

      console.log('響應信息:',resp);

      console.log('響應體:',resp.body['data']);

      })

      }

      sendPost(){

      this.heroService.createHero({name:'Dash'}).subscribe(resp=>{

      console.log('響應信息:',resp);

      console.log('響應體:',resp.body['data']);

      })

      }

      控制臺打印的信息可以看到后臺的虛擬數據已經被請求到了:

      三. 使用Rxjs構建Http請求結果的處理管道

      3.1 基本示例

      盡管看起來Http請求的返回結果是一個可觀測對象,但是它卻沒有map方法,當需要對http請求返回的可觀測對象進行操作時,可以使用pipe操作符來實現:

      import { Observable, of, from} from 'rxjs';

      import { map , tap, filter, flatMap }from 'rxjs/operators';

      /*構建一個模擬的結果處理管道

      *map操作來獲取數據

      *tap實現日志

      *flatMap實現結果自動遍歷

      *filter實現結果過濾

      */

      getHeroes$(): Observable>{

      return this.http.get(this.all_hero_api,{observe:'response'})

      .pipe(

      【響應式編程的思維藝術】 (5)Angular中Rxjs的應用示例

      map(resp=>resp.body['data']),

      tap(this.log),

      flatMap((data)=>{return from(data)}),

      filter((data)=>data['index'] > 1)

      );

      }

      很熟悉吧?經過處理管道后,一次響應中的結果數據被轉換為逐個發出的數據,并過濾掉了不符合條件的項:

      3.2 常見的操作符

      Angular中文網列舉了最常用的一些操作符,RxJS官方文檔有非常詳細的示例及說明,且均配有形象的大理石圖,建議先整體瀏覽一下有個印象,有需要的讀者可以每天熟悉幾個,很快就能上手,運算符的使用稍顯抽象,且不同運算符的組合使用在流程控制和數據處理方面的用法靈活多變,也是有很多套路的,開發經驗需要慢慢積累。

      四. 冷熱Observable的兩種典型場景

      原文中提到的冷熱Observable的差別可以參考這篇文章【RxJS:冷熱模式的比較】,概念本身并不難理解。

      4.1 shareReplay與請求緩存

      開發中常會遇到這樣一種場景,某些集合型的常量,完全是可以復用的,通常開發者會將其進行緩存至某個全局單例中,接著在優化階段,通過增加一個if判斷在請求之前先檢查緩存再決定是否需要請求,Rxjs提供了一種更優雅的實現。

      先回顧一下上面的http請求代碼:

      getHeroes(): Observable>{

      return this.http.get(this.all_hero_api,{observe:'response'});

      }

      http請求默認返回一個冷Observable,每當返回的流被訂閱時就會觸發一個新的http請求,Rxjs中通過shareReplay( )操作符將一個可觀測對象轉換為熱Observable(注意:shareReplay( )不是唯一一種可以加熱Observable的方法),這樣在第一次被訂閱時,網絡請求被發出并進行了緩存,之后再有其他訂閱者加入時,就會得到之前緩存的數據,運算符的名稱已經很清晰了,【share-共享】,【replay-重播】,是不是形象又好記。對上面的流進行一下轉換:

      getHeroes$(): Observable>{

      return this.http.get(this.all_hero_api,{observe:'response'})

      .pipe(

      map(resp=>resp.body['data']),

      tap(this.log),

      flatMap((data)=>{return from(data)}),

      filter((data)=>data['index'] > 1),

      shareReplay() // 轉換管道的最后將這個流轉換為一個熱Observable

      )

      }

      在調用的地方編寫調用代碼:

      sendGet(){

      let obs = this.heroService.getHeroes$();

      //第一次被訂閱

      obs.subscribe(resp=>{

      console.log('響應信息:',resp);

      });

      //第二次被訂閱

      setTimeout(()=>{

      obs.subscribe((resp)=>{

      console.log('延遲后的響應信息',resp);

      })

      },2000)

      }

      通過結果可以看出,第二次訂閱沒有觸發網絡請求,但是也得到了數據:

      網絡請求只發送了一次(之前的會發送兩次):

      4.2 share與異步管道

      這種場景筆者并沒有進行生產實踐,一是因為這種模式需要將數據的變換處理全部通過pipe( )管道來進行,筆者自己的函數式編程功底可能還不足以應付,二來總覺得很多示例的使用場景很牽強,所以僅作基本功能介紹,后續有實戰心得后再修訂補充。Angular中提供了一種叫做異步管道的模板語法,可以直接在*ngFor的微語法中使用可觀測對象:

      • {{contact.name}}

      • {{contact.name}}

      示例:

      this.contacts = http.get('contacts.json')

      .map(response => response.json().items)

      .share();

      setTimeout(() => this.contacts2 = this.contacts, 500);

      五. 一點建議

      一定要好好讀官方文檔。

      華為云APP 面向對象編程

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:kubernetes基本概念及操作命令
      下一篇:Google鼓勵的13條代碼審查標準
      相關文章
      亚洲网站在线观看| 麻豆亚洲AV永久无码精品久久| 亚洲国产午夜电影在线入口| 色拍自拍亚洲综合图区| 亚洲精品无码午夜福利中文字幕 | 亚洲一区二区三区播放在线| 亚洲综合一区二区国产精品| 亚洲精品免费在线观看| 日韩亚洲AV无码一区二区不卡 | 亚洲资源在线观看| 亚洲资源在线观看| 亚洲国产综合人成综合网站00| 亚洲成a人片在线观看中文app| 亚洲制服在线观看| 亚洲中文字幕乱码熟女在线| 亚洲熟女综合色一区二区三区| 亚洲爆乳成av人在线视菜奈实 | 亚洲黄色免费在线观看| 亚洲福利一区二区三区| 亚洲伊人久久精品| 日韩亚洲国产综合高清| 亚洲精品久久久久无码AV片软件| 亚洲AV成人精品一区二区三区| 丁香亚洲综合五月天婷婷| 亚洲精品麻豆av| 亚洲人成精品久久久久| 久久久久久亚洲精品中文字幕| 日韩亚洲Av人人夜夜澡人人爽| 97亚洲熟妇自偷自拍另类图片 | 亚洲国产成人乱码精品女人久久久不卡| 亚洲不卡无码av中文字幕| 国产亚洲午夜高清国产拍精品| 亚洲精品自产拍在线观看| 亚洲国产综合专区在线电影| 亚洲国产精品网站久久| 亚洲欧美日本韩国| 亚洲男人av香蕉爽爽爽爽| 亚洲国产精品va在线播放| 亚洲视频在线观看网址| 亚洲依依成人亚洲社区| 怡红院亚洲红怡院在线观看|