【问题标题】:Convert Array to Observable, perform transformations and return again as Array?将 Array 转换为 Observable,执行转换并再次返回为 Array?
【发布时间】:2016-06-24 04:45:24
【问题描述】:

ngOnInit() 我有“return x”,我想将它放入Observable,然后执行转换并以相同的格式再次返回。

这里是工作插件: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')
  }      
}

【问题讨论】:

  • 你有什么问题?
  • 你可以看一下代码,有注释掉的部分。变量 x 应该是可观察的,然后是 .map 或类似的东西,然后作为 x 数组返回,它将通过 return 语句传播到模板。
  • 但是你想用它实现什么?为什么需要将 Array 转换为 Observable 只是为了将其转换回 Array?
  • 因为我想通过 Observable 机器 (rxjs) 使用该强大的工具集来转换 Array 中的数据,然后当我完成后,只需将其返回给 Array 即可提供模板通过 Observable 和 |异步的。就在“return x”之前似乎是完美的地方。

标签: typescript angular rxjs rxjs5 reactive-extensions-js


【解决方案1】:

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

【讨论】:

  • 谢谢拉迪姆。这里的重点是更改“this.data”,当更改时,可观察对象捕获它并通过其运算符机制运行,然后返回我可以在模板中迭代的数组。当我使用“.of”运算符时,它就像那样工作,但是我不能使用强大的 rxjs 工具箱进行数据转换。我试图把它放在 map(x => x + " some text" ) 但它包含整个数组,而不是单独的值,所以这是不可能的。如果我使用 .from,我在操作 this.data 时不会得到更新。这里的重点是在 this.data 中有状态,它通过 Obs 运行。更新并返回解析后的数据。
  • 泰迪,给我一个解决方案的机会。想想看。如果你想观察数组(string[] 数组原样),你必须自己创建很多东西。事件、处理程序......全新的 RX JS 可观察。我的解决方案是 gen++。它已经从将该案例转移到 Observable 中获利……然后只是从内置解决方案中获利。我们只是使用 startWith 来消耗现有的数组。之后,任何事件都将转换为带有新项目的发射。我们的扫描已准备好并返回调整后的数组。我们甚至可以添加更多运营商...请给我一个机会...它会成为你的方式;);)
  • 你的解决方案真的很聪明,但它并没有解决我的问题。我又看了一遍代码。我需要的是:1.更改“this.data”数组,2.使用“.of”使其同步通过 | 订阅的 Observable模板中的异步。 3. 在输入“this.data”和“this.data$”之间放置使用 rxjs 转换的能力。这就像超级疯狂的不可变自我更新应用程序。然后我只需要用正确的数据更新“this.data”,让 RxJS 发挥它的魔力,我就完成了。你的问题是不只是添加项目,还需要从数组中删除、拼接和其他东西。
  • 我扩展了我的答案,创建了全新的、更复杂的 plunker.. 现在你有了真正做很多事情的解决方案.. 而代码量几乎为零 ;) 只是.. 所有的东西是关于可观察的,而不是关于字符串 []...希望能有所帮助
  • plnkr.co/edit/ExqxywBeud2gkHr41pCm?p=preview 我添加了一个重置​​“this.data”数组的函数,该数组应该传播到视图。我需要这个功能才能工作。我真的很喜欢你在这里使用的东西,非常高级的东西,但我需要直接更改 this.data。如果没有人发布更好的答案,我一定会接受你的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-09
  • 2014-10-24
  • 2015-01-09
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多