将 Array 转换为 Observable,执行转换并再次 return 作为 Array?

Convert Array to Observable, perform transformations and return again as Array?

ngOnInit() 中,我有 "return x",我想将其放入 Observable,然后以相同的格式再次执行转换和 return。

这是工作中的 plunker:http://plnkr.co/edit/z26799bSy17mAL4P5MiD?p=preview

import {Component} from '@angular/core'
import { Observable } from 'rxjs'
import * as Rx from 'rxjs/Rx'

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2>{{name}}</h2>

      <button (click)="addToArray()">Add</button>
      <ul>
        <li *ngFor="let item of data$ | async">{{ item }}</li>
      </ul>

    </div>
  `,
  directives: []
})
export class App {

  data = ["one","two","three"]
  data$: Observable<Array<string>>;

  constructor() {
    this.name = 'Angular2 array to observable example'
  }

  ngOnInit() {
    this.data$ = Rx.Observable.of(this.data)
      .map(data => {
        let x = data
        x.push("4")

        ///
        ///  TRANSFORM X IN THIS SECTION OF THE CODE
        ///  HERE BY PUTTING IT INTO OBSERVABLE
        ///  PERFORMING TRANSFORMATIONS AND
        ///  RETURNING THE DATA TO BE RENDERED IN TEMPLATE
        ///

        return x
      })
  }

  addToArray() {
    this.data.push('more numbers')
  }      
}

an adjusted and wirking plunker

我会用一个 EventEmitter 和几个运算符来实现它,主要是

调整后的代码

  data = ["one","two","three"]
  data$: Observable<string[]>;
  protected emitter = new EventEmitter<string[]>(); 

  constructor() {
    this.name = 'Angular2 array to observable example'
    this.data$ = this.emitter
      .startWith(this.data)
      .scan((orig, item) => orig.concat(item))
  }

  ngOnInit() {
    // this.data$ = Rx.Observable.of(this.data)
    //  .map(data => {
    //    let x = data
    //    x.push("4")
    //    return x
    //  })
  }

  addToArray() {
    //this.data.push('more numbers')
    this.emitter.emit("forth")
  }

检查一下here

延长

很多more complex plunker

还有更复杂的解决方案..只是从 Observable 及其中获利 运营商。已准备好添加删除 项:

  data = ["one","two","three"]
  data$: Observable<string[]>;
  protected emitter = new EventEmitter<string[]>(); 
  protected toDelete = new Rx.BehaviorSubject<string[]>([])
    .scan((orig, item) => orig.concat(item));

  constructor() {
    this.name = 'Angular2 array to observable example'
    this.data$ = this.emitter
      // start
      .startWith(this.data)
      // return array
      .scan((orig, item) => orig.concat(item))
      // adjust each source string with a prefix
      .map((coll: string[]) => {
        let adjusted: string[] = []
        coll.forEach(item => {
          adjusted.push("x" + item)
        })
        return adjusted;
      })
      // now consume also array of items to be deleted
      .combineLatest(this.toDelete)
      // just those which were not delted
      .map(([all, toDelete]:[string[], string[]]) =>{
        let result = all.filter( function( el ) {
          return toDelete.indexOf( el ) < 0;
        });
        return result;
      })
  }

  counter: int = 0;
  addToArray() {
    this.emitter.emit(`other${++this.counter}`)
  }

  deleteFromArray(removeString) {
    this.toDelete.next(removeString)
  }

action here

中查看

让我们再做一次 EXTEND

有个final plunker with lot of data: string\[\] array handling

我们现在甚至可以跟踪变化,让他们调整原来的数据数组,甚至可以使用RESET功能,重新开始。这是调整后的代码:

  data = ["one","two","three"]
  data$: Observable<string[]>;
  protected emitter: EventEmitter<string[]>;
  protected toDelete: Rx.BehaviorSubject<string[]>;

  constructor() { 
    this.initEmitters();  
    this.data$ = this.createObservable(this.data);
  }

  initEmitters() {
    this.emitter = new EventEmitter<string[]>(); 
    this.toDelete = new Rx.BehaviorSubject<string[]>([])
      .scan((orig, item) => orig.concat(item));
  }

  createObservable(initData)
  {
    let observable = this.emitter
      // start
      .startWith(initData)
      // return array
      .scan((orig, item) => orig.concat(item))
      // adjust each source string with a prefix
      .map((coll: string[]) => {
        let adjusted: string[] = []
        coll.forEach(item => {
          adjusted.push("x" + item)
        })
        return adjusted;
      })
      // now consume also array of items to be deleted
      .combineLatest(this.toDelete)
      // just those which were not delted
      .map(([all, toDelete]:[string[], string[]]) =>{
        let result = all.filter( function( el ) {
          return toDelete.indexOf( el ) < 0;
        });
        return result;
      })

      observable
        .subscribe((currentData) => {
          this.data.length = 0;
          [].push.apply(this.data, currentData)
        });

      return observable;
  }

  counter: int = 0;
  addToArray() {
    this.emitter.emit(`other${++this.counter}`)
  }

  deleteFromArray(removeString) {
    this.toDelete.next(removeString)
  }

  resetArray() {
    this.initEmitters();  
    this.data$ = this.createObservable(['ten','eleven'])
  }

测试 array vs obesrvable in action here