如何快速使用 Rxjs

ReactiveX 结合了 观察者模式、迭代器模式 和 使用集合的函数式编程,以满足以一种理想方式来管理事件序列所需要的一切。

基本概念

为什么要学习Rxjs呢?
因为它是Promise 的超集;
Promise 有一个缺点,那便是一旦调用了resolve或者是reject之后便返回了. 不能再次使用resolve 或者是reject ; 想象一下, 若是从端口源源不断地发出消息;每次收到的消息就要通知.回掉函数来处理, 那该怎么办呢?
于是 , 伟大的Rx 就有出现了 ~

还有在angular4+ 的开发中, Rxjs 是必学的;

在 RxJS 中用来解决异步事件管理的的基本概念是:

Observable (可观察对象): 表示一个概念,这个概念是一个可调用的未来值或事件的集合。
Observer(观察者): 一个回调函数的集合,它知道如何去监听由 Observable 提供的值。
Subscription (订阅): 表示 Observable 的执行,主要用于取消 Observable 的执行。
Operators (操作符): 采用函数式编程风格的纯函数 (pure function),使用像 map、filter、concat、flatMap 等这样的操作符来处理集合。
Subject (主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。
Schedulers (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout 或 requestAnimationFrame 或其他。

安装

  • Rxjs安装 安装细节(略)

实战前准备

在工作区里面建立简单的html 页面


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Rx学习title>
head>
<body>
<input type="text">
<div id="result">div>
body>

<script src="https://cdn.bootcss.com/rxjs/6.0.0-alpha.3/Rx.min.js">script>




html>

Observable是什么?

/**
 * 这里把foo 看成一个函数,意味着每次调用foo 时都回导致传入Rx.Observable.create里的回调重新执行一次,
 * @type {Observable|*}
 */
let foo = Rx.Observable.create(observer => {
    console.log("hello")
    // observer.next表示一个返回值,当然可以多次调;
    // 每次调用后会将next里面的值返回给 foo.subscribe里面的回掉,执行完后再返回
    observer.next(42)
});
//foo.subscribe调用方法相当与foo(); 为了通过里面的回掉函数来获取值;
foo.subscribe(x => console.log(x))
foo.subscribe(y => console.log(y))

Observable里面怎么控制流的 ?

// Observable里面怎么控制流的 ?
var observable = Rx.Observable.create(observer => {
    try {
        observer.next(1)
        observer.next("hello")
        observer.next(2)
        observer.next(3)
        // 到这步就完成了. 面的next 就不会执行了
        observer.complete();
        observer.next(4)
    } catch (err) {
        observer.error(err)
    }

})
// 这么看observable.subscribe 怎么封装的callback
var observer = {
    next(value) {
        console.log(value)
    },
    complete() {
        console.log('完成')
    },
    error(err) {
        console.log(value)
    }
}
let subcription = observable.subscribe(observer)

subscription陷阱

//  Rx.Observable.interval可以返回一个能够发射(返回123的数字) 间隔时1000毫秒
var observable = Rx.Observable.interval(1000);
var subscription = observable.subscribe(x => console.log(x));
setTimeout(()=>{
    //subscription里面的有个方法 unsubscribe可以取消订阅observable里发射的数据
    // 但是Observable仍然在吐数字
    subscription.unsubscribe();
},3000)

Subject发射器

// Subject是一种能够发射多个数据给observer的Observable, 看起来好像是EventEmintter
var subject=new Rx.Subject();
subject.subscribe({
    next:(v=>{console.log("a:"+v)})
});
subject.subscribe({
    next:(v=>{console.log("b:"+v)})
})
subject.next(1)
subject.next(2)

// 与Observable不同的是, Subject发射数据给多个observer. 其次,定义subject时没有传入callback;
// 是因为subject 它自带next ,complete ,error 等方法;从而可以发射数据给observer,
// observer不知道数据是  Observable 还是subject给的数据;透明的;
// 而且,subject有各种派生


// BehaviorSubject能够保留最近的数据,使得当有subscribe的时候,立马能发射出去
// ReplaySubject 能够保留最近的一些数据, 使得当有subscript的时候,将这些数据发射出去
// AsyncSubject 只会发射结束前的一个数据
// Multicasted Observables 是一种借助Subject来讲数据发射给多个observer的Observable

我们经常听到的响应式编程是怎么实现的呢?

var a,b=1,c=2;
a=b+c;
console.log("b=" + b);
console.log("c=" + c);
console.log("a=" + a);
b=3;
c=2;
console.log("a=" + a);
// 在传统编程中 a 的值不会随着bc变

// 那么在响应式编程中的怎么实现呢?
/*
* 1,操作符 : from zip等.. Rx里面有太多着这样的操作符:创建类,变换类,过滤类,合并类,处理错误类,工具类,数学类等等
* 2,lamda表达式 =>: 可以把他想成一个数据的指向,左边获取数据,右边处理输出数据;
* */

//为什么规范性 "b$" 命名呢?   加了$ 说明是一个流操作;
var b$=Rx.Observable.from([1,3]);
var c$=Rx.Observable.from([2,2]);
var a$=Rx.Observable.zip(b$,c$,(b,c)=>{
    console.log("b=" + b);
    console.log("c=" + c);
    return b+c;
})
a$.subscribe(a=>{console.log("a=" + a);})

Rx 再体验;


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Rx再体验title>
    <script src="https://code.jquery.com/jquery-3.1.0.js">script>
    <script src="https://cdn.bootcss.com/rxjs/6.0.0-alpha.3/Rx.min.js">script>
head>
<body>
<input type="text" name="" id="todo">
<button id="addBtn">addbutton>
<script>
    //一般Rxjs里面一边在Observable类型的变量后面加了$标识,这就是一个流变量,预定熟成的

    //显示获取todo输入框对象, 然后定义一个观察者对象,将todo的keyup事件转化成一个数据流,
    // 然后订阅这个数据流再input 中显示
    // filter 过滤器
    // map 允许对数据流每个元素进行函数,
    //map使用的场景太多. rx团队准们搞出了 pluck 操作符;从事一系列嵌套属性中把值提取出来形成新的流.
    let todo = document.getElementById('todo');
    let input$ = Rx.Observable.fromEvent(todo, 'keyup');
    // input$
    // .filter(ev => ev.keyCode == 32)
    // .map(ev=>ev.target.value*10)
    //     .pluck('target', 'value')
        // .subscribe(value => console.log(value.target.value))

    //from操作符:可以支持数组,类数组的对象. promise iterable对象或类似Observable的对象
    // 这个操作符应该是可以创建Observable的操作符中最常用的一个.几乎可以把任何对象换成Observable.

    var button = document.querySelector('button');
    Rx.Observable.fromEvent(button, 'click')
        .throttleTime(1000)
        .map(event => event.clientX)
        .scan((count, clientX) => count + clientX, 0)
        .subscribe(count => console.log(count));
script>
body>
html>

湿滑的combineLatest


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Rx学习title>
head>
<body>
<h4>我们做一个简单的BMI 公式h4>
weight:
<input type="number" id="weight">kg
<br>
height:
<input type="number" id="height"> cm
<br>
Your BMI is
<div id="bmi">div>

body>

<script src="https://cdn.bootcss.com/rxjs/6.0.0-alpha.3/Rx.min.js">script>
<script>
    let weight = document.getElementById('weight');
    let height = document.getElementById('height');
    let bmi = document.getElementById('bmi');

    let weight$ = Rx.Observable.fromEvent(weight, 'input')
        .pluck('target', 'value')
    let height$ = Rx.Observable.fromEvent(height, 'input')
        .pluck('target', 'value')
    let bmi$ = Rx.Observable.combineLatest(weight$, height$, (w, h) => w / (h * h / 100 / 100))
    bmi$.subscribe(b => bmi.innerHTML = b)

    //这里combineLatest的逻辑不要太湿滑, 
    //combineLatest和zip不一样; 
script>
html>

这里推荐学习文档: https://ithelp.ithome.com.tw/users/20103367/articles
官网: https://cn.rx.js.org/manual/overview.html#-

你可能感兴趣的:(JavaScript,语言新发展,vue+,/,react+,/,angular+)