将数据从一个observable传递到另一个observable的更好方法

时间:2016-10-04 12:11:27

标签: angular rxjs observable

我创建了两个用于测试Observables的函数,每个函数都返回一个Observable

foo() {
  return new Observable(observer => {
    let i = 0;
    setInterval( () => {
      if(i === 10) {
        observer.complete();
      } else {
        observer.next(i);
        i++;
      }
    }, 1000);
    // If I call observer.complete() here then it never completes
  });
}

bar(fooResult) {
  return new Observable(observer => {
    let j = 0;
    setInterval( () => {
      if(fooResult) {
        observer.next('j -> '+j+' plus fooResult '+JSON.stringify(fooResult));
        observer.complete();
      } else {
        observer.next(j);
        j++;
      }
    }, 2000);
  });
}

并像这样使用它们:

    let fooResult = [];

    // Testing observables...
    this.exampleProductService.foo().subscribe(
      (res) => { 
        console.log('foo next() -> '+res);
        fooResult.push(res);
      },
      (err) => {
        console.error('foo error: '+JSON.stringify(err));
      },
      () => { 
        console.log('foo finished');
        this.exampleProductService.bar(fooResult).subscribe(
          (res) => {
            console.log('bar next() -> '+res);
          },
           (err) => {
            console.error('bar error: '+JSON.stringify(err));
          },
          () => {
            console.log('bar finished');
          }
        );
      }
    );

提出问题:

  1. 是否有更好的方法将数据从完成Observable传递到另一个也返回Observable的函数?构建数组似乎很麻烦,我不能执行以下操作,因为complete callback的{​​{1}}部分未传递ObservableprogressUpdate等参数:

    onError
  2. 我尝试将第一个函数的结果赋给变量,然后传递该变量,但是,正如预期的那样,我得到了一个Observable而不是我想要的结果。

  3. 关于我上面的做法有什么不对吗?

  4. 由于

    P.S。这是一个Angular 2应用程序!

2 个答案:

答案 0 :(得分:3)

我认为你的功能有点过于复杂。例如,当工厂函数已经可用时,不要使用构造函数,在这种情况下{@ 1}}或interval正如@Meir指出的那样,尽管在这种情况下它会更详细。 / p>

其次,timer功能并没有真正有意义,因为你似乎在等待一些你已经知道已经完成的事情(因为你没有订阅)直到由bar生成的Observable的完成块。

我根据你声明的目标等待重构一个foo,然后开始第二个,同时使用第一个中的第一个结果。

Observable

现在使用它们时,你会改为:

// Factory function to emit 10 items, 1 every second
function foo() {
  return Observable.interval(1000)
    .take(10);
}

// Lifts the passed in value into an Observable and stringfys it
function bar(fooResult) {
  return Rx.Observable.of(fooResult)
    .map(res => JSON.stringify(fooResult))
}

上面注意我也摆脱了全局状态,这是函数式编程的诅咒。在任何可能的情况下,您的州应该本地化为流。

请参阅此处的工作示例:http://jsbin.com/pexayohoho/1/edit?js,console

答案 1 :(得分:1)

我不确定您要实现的目标,但这是jsbin that尝试复制您的代码。

很少有事情需要注意:

使用Observable.timer和.take()运算符可以更容易地创建foo()。

你的bar()可以被另一个带有map和.takeWhile()运算符的计时器使用。

至于最后一个订阅(完整部分),它只打印'foo finished'但没有别的,因为它订阅了已经终止的非缓冲序列。