添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
https://rxmarbles.com/
2019 ng conf
RXJS Operators in 20 minutes | Mike Brocchi & John Niedzwiecki
https://www.youtube.com/watch?v=ak3MvMn8u18&list=PLOETEcp3DkCpimylVKTDe968yNmNIajlR&index=48

[S05E06] RxJS 運算子全面解析
https://www.youtube.com/watch?v=DPyZq74V60o&list=PL9LUW6O9WZqgUMHwDsKQf3prtqVvjGZ6S&index=17

今天由Will保哥分享,很多時間是大家在想operator的實際應用
這一集片長2個小時,所以拆成2天po

投影片找不到,所以手搭一下第1頁

很精簡的練習環境

npm i -g webpack webpack-cli webpack-command lite-server typescript
npm init -y
tsc --init
npm i rxjs ts-loader typescript
mkdir src
mkdir src
  • src/index.ts
  • import { of } from 'rxjs';
    import { map } from 'rxjs/operators';
    let ob = of(1,2,3);
    ob.pipe(map(v => v*5))
        .subscribe(v => console.log(v));
    
  • src/index.html
  • html:5 snippet
    <!DOCTYPE html>
    <html lang="zh-Hant-TW"> 如果用en的話,chrome會跳出要不要翻譯
        <meta charset="UTF-8">
        <meta name="viewport content="width=device-width, initial-scale=1.0, 
                    minimum-scale=1, maximum-scale=1"> 
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^避免手機的browser快速點2下就放大
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <script src="dist/bundle.js"></script>
    </head>
    </body>
    </html>
    

    3.webpack.config.js

    module.export = {
        entry: {
            vendor: "./src/index.ts"
        mode: "development",
        module: { 
            rules:[
                        test: /\.tsx?$/,
                                   ^^ tsx是react,?代表option 非必要,ts、tsx皆處理
                        loader: 'ts-loader'
        plugins:[
        output:{ 編譯到dist/bundle.js讓index.html引入
          filename: "bundle.js",
        resolve:{
            extensions: ['.js','.jsx','.ts','.tsx']
    

    以上設好環境就,就可以上路啦~
    設不起來,用Angular專案也能玩

    wp -w
    lite-server # 存檔立刻看結果
    

    VS Code 安裝 Quokka.js

    以前都裝失敗,這一次竟然成功了,開心~
    不知道跟wallaby有什麼不同?

    VS Code 安裝 Quokka.js Extension

    npm i -g typescript
    npm init -y
    tsc --init
    npm i rxjs
    

    index.js

    import { of } from 'rxjs';
    import { filter } from 'rxjs/operators';
    // 1. of餵數列
    var ob = of(1,2,3,4,5); // 建一個最簡單的observable
             ^^ 屬於建立observable的operator,直接把數列轉為observable
    // 2. of餵array
    var items = [1,2,3,4,5];
    var ob2 = of(...items);
    ob.subscribe((v) => {
        console.log(v);
    // 轉成observable後可以做很多操作,語法簡潔、語意好懂
    // 範例1:做filter,用pipe再接operator
    ob.pipe( // pipe是著跟observable的型別走,不用import
        filter((v) => (v % 2 == 0)
    

    後面的程式碼就打面斷囉

    fromEvent

    https://rxjs-dev.firebaseapp.com/api/index/function/fromEvent
    把DOM EventTarget轉成Observable
    轉成observable,再subject取得event的資料流後,就可以做超多事!!

    fromEvent<T>(target: FromEventTarget<T>, eventName: string, options?: EventListenerOptions
                         ^^^^^^^^^^^^^^^^^^ DOM EventTarget
    | ((...args: any[]) => T), resultSelector?: ((...args: any[]) => T)): Observable<T>
    // 最常用的就前面2個參數 target: FromEventTarget<T>, eventName: string
    // 官網範例
    import { fromEvent } from 'rxjs';
    // 把document的click event轉成observable
    const clicks$ = fromEvent(document, 'click');
                ^加$較好分辨   ^^^^^^^^   ^^^^^
    clicks$.subscribe(x => console.log(x));
    

    感謝will保哥重要科普(不會的賺到囉)

  • 觀查MouseEvent
    在chrome的console可以觀查event事件 這個object 及其上層object
    每一層的object都有不同的屬性方法,可以查文件,進而利用
  • // MouseEvent
    f MouseEvent() { [native code] }
    ^ 是一個function
    // MouseEvent.__proto__
                 ^^^^^^^^^ 上一層的object
    f UIEvent() { [native code] }
      ^^^^^^^ 是UIEvent()
    // MouseEvent.__proto__.__proto__ 上一層的上一層object  
    f Event() { [native code] }
    // MouseEvent.__proto__.__proto__.__proto__  
    f() { [native code] }
    
  • 觀查document(window下的一個屬性)
  • // document
    #document
    // document.__proto__ 
    HTMLDocument {constructor:f, Symbol(Symbol.toStringTag):"HTMLDocument"}
    ^^^^^^^^^^^^ 所有document都繼承HTMLDocument
    // document.__proto__.__proto__
    Document {...}
    // document.__proto__.__proto__.__proto__
    Node {ELEMENT_NODE:1, ATTRIBUTE_NODE:2, TEXT_NODE:3, ...}
    ^^^^ 一個網頁的節點
    // document.__proto__.__proto__.__proto__.__proto__
    EventTarget {addEventListener:f, removeEventListener:f, ...}
    ^^^^^^^^^^^ 所有DOM往上找都會有EventTarget
    fromEvent<T>(target: FromEventTarget<T>,...
                             ^^^^^^^^^^^ 所有型別都會有的EventTarget,就是指這個
    // document.__proto__.__proto__.__proto__.__proto__.__proto__
    {constructor:f, __defineGetter__:f, __defineSetter__:f,...}
    (root)根物件
    

    from()

    類似of(),差別在於from可以直接傳入array
    from([10,20,30])

    https://rxjs-dev.firebaseapp.com/api/index/function/from
    Creates an Observable from an Array, an array-like object, a Promise, an iterable object, or an Observable-like object.

    from<T>(input: ObservableInput<T>, scheduler?: SchedulerLike): Observable<T>
    ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^

    fromPromise()好像不見了,官網文件找不到
    可能是RxJS6拿掉了,想看只能到舊文件找了
    https://cn.rx.js.org/class/es6/Observable.js~Observable.html#static-method-fromPromise

    var ob = from(fetch('data.json'));
                   ^^^^^ fetch()可以用.json()轉json
    // data.json {id:1, name:"Will"}
    ob.pipe().subscribe((v:any)=>{
        var ob2 = from(v.json());
                       ^^^^^^^^ 回傳promise
        ob2.subscribe((xx:any)=>{
            console.log(xx.json());
    

    然後… create()運算子也沒了…
    變成Observable.create()

    bindCallback

    https://rxjs-dev.firebaseapp.com/api/index/function/bindCallback

    傳入callback function,會自動把callback function轉成observable

    Converts a callback API to a function that returns an Observable.

    bindCallback<T>(callbackFunc: Function, resultSelector?: Function | SchedulerLike, scheduler?: SchedulerLike): (...args: any[]) => Observable<T>
    
    import { bindCallback } from 'rxjs';
    import * as jQuery from 'jquery';
    // Suppose we have jQuery.getJSON('/my/url', callback)
    // 只要callbackFunc的signature用法是 ^^^^^^ 配 ^^^^^^ callback function
    // 就可以用bindCallback來binding
    const getJSONAsObservable = bindCallback(jQuery.getJSON);
                                                    ^^^^^^^ 這是function
    const result = getJSONAsObservable('/my/url');
    result.subscribe(x => console.log(x), e => console.error(e));
    

    repeat()

    https://rxjs-dev.firebaseapp.com/api/operators/repeat

    Returns an Observable that will resubscribe to the source stream when the source stream completes, at most count times.

    repeat<T>(count: number = -1): MonoTypeOperatorFunction<T>
    ^^^^^ 會重覆的subscribe n次

    (a)--(b)--(complete)
    如果count=3的話
    會變成重覆3次
    (a)--(b)--(a)--(b)--(a)--(b)--(complete)

    defer()

    https://rxjs-dev.firebaseapp.com/api/index/function/defer

    Creates an Observable that, on subscribe, calls an Observable factory to make an Observable for each new Observer.

    defer<R extends ObservableInput<any> | void>(observableFactory: () => R): Observable<ObservedValueOf<R>>

    import { defer, fromEvent, interval } from 'rxjs';
    const clicksOrInterval = defer(function () {
                                   ^^^^^^^^^^^ 放一個callback function
                                               Observable factory
      return Math.random() > 0.5
        ? fromEvent(document, 'click')
        : interval(1000);
    clicksOrInterval.subscribe(x => console.log(x));
                     ^^^^^^^^^ 有observer訂閱的時候,就各別呼叫Observable factory
                               產生observable給observer