摘要:本文是響應式編程第四章構建完整的應用程序這篇文章的學習筆記。涉及的運算符每隔指定時間將流中的數據以數組形式推送出去。中提供了一種叫做異步管道的模板語法,可以直接在的微語法中使用可觀測對象示例五一點建議一定要好好讀官方文檔。
本文是【Rxjs 響應式編程-第四章 構建完整的Web應用程序】這篇文章的學習筆記。示例代碼托管在:http://www.github.com/dashnowords/blogs
博客園地址:《大史住在大前端》原創博文目錄
華為云社區地址:【你要的前端打怪升級指南】
[TOC]
一. 劃重點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( 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的微語法中使用可觀測對象:
示例:
this.contacts = http.get("contacts.json") .map(response => response.json().items) .share(); setTimeout(() => this.contacts2 = this.contacts, 500);五. 一點建議
一定要好好讀官方文檔。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/110248.html
摘要:由于技術棧的學習,筆者需要在原來函數式編程知識的基礎上,學習的使用。筆者在社區發現了一個非常高質量的響應式編程系列教程共篇,從基礎概念到實際應用講解的非常詳細,有大量直觀的大理石圖來輔助理解流的處理,對培養響應式編程的思維方式有很大幫助。 showImg(https://segmentfault.com/img/bVus8n); [TOC] 一. 響應式編程 響應式編程,也稱為流式編程...
摘要:本文是響應式編程第一章響應式這篇文章的學習筆記。通過代碼對比可以發現,在響應式編程中,我們不再用對象的概念來對現實世界進行建模,而是使用流的思想對信息進行拆分和聚合。 本文是Rxjs 響應式編程-第一章:響應式這篇文章的學習筆記。示例代碼地址:【示例代碼】 更多文章:【《大史住在大前端》博文集目錄】 showImg(https://segmentfault.com/img/bVbuE...
摘要:本文是響應式編程第二章序列的深入研究這篇文章的學習筆記。函數科里化的基本應用,也是函數式編程中運算管道構建的基本方法。四資料參考函數式編程指南 本文是Rxjs 響應式編程-第二章:序列的深入研究這篇文章的學習筆記。示例代碼托管在:http://www.github.com/dashnowords/blogs 更多博文:《大史住在大前端》目錄 showImg(https://segme...
摘要:發布通過回調方法向發布事件。觀察者一個回調函數的集合,它知道如何去監聽由提供的值。 本文目錄 一、項目起步 二、編寫路由組件 三、編寫頁面組件 1.編寫單一組件 2.模擬數據 3.編寫主從組件 四、編寫服務 1.為什么需要服務 2.編寫服務 五、引入RxJS 1.關于RxJS 2.引入RxJS 3.改造數據獲取方式 六、改造組件 1.添...
摘要:響應式命令式這兩種編程風格的思維方式是完全相反的。第二種方式是工人主動去找工人索取生產手機所要的零件,然后生產一臺完整的手機,這兩種方式就對應的響應式和命令式。 angular2中內置了rxjs,雖然框架本身并沒有強制開發者使用響應式風格來組織代碼,但是從框架開發團隊的角度可以看出他們必然是認同這種編程風格的。rxjs本質是基于函數式編程的響應式風格的庫,函數式相對于面向對象來說更加抽...
閱讀 1369·2021-10-19 11:42
閱讀 717·2021-09-22 16:04
閱讀 1867·2021-09-10 11:23
閱讀 1838·2021-07-29 14:48
閱讀 1247·2021-07-26 23:38
閱讀 2812·2019-08-30 15:54
閱讀 1024·2019-08-30 11:25
閱讀 1694·2019-08-29 17:23