首页 > 解决方案 > 如何在 observable 内部有条件地订阅,等待响应并返回完整结果?

问题描述

我有一个Observable这样的Promise(我使用严格的打字稿):

let foo: Subscription = from(channel.getMessages).pipe(flatMap((data: any) => data.items))

// then I subscribe to it like this
foo.subscribe((val: any) => console.log(val))

我需要输入管道flatMap,因为该channel对象有一个items包含所有文本消息的数组属性。这将非常简单,但是有些消息是媒体类型的,在这些情况下,我必须对media.getContentUrl(也是 a Promise)进行另一个请求。所以在这种情况下,我必须取回媒体url而不是短信正文。

到目前为止,我尝试做类似的事情:

let foo = from(channel.getMessages)
            .pipe(
              flatMap(data => data.items), 
              map((item: any) => {
                if (item.type === 'media') {
                  return from(item.media.getContentUrl).subscribe((val: any) => val);
                }
                return item.body;
              })
            );

这将item.body正确返回,但当消息为media类型时会出错:TypeError: You provided 'function getContentUrl(): ... where stream was expected

我的目标是有一个可观察的,我在其中收到消息,但是当消息类型是媒体时,我发送另一个请求,等待它,然后我将所有内容重新组合在一起,例如,在我取回数据后,我的数组将如下所示:

messages = [
  'foo',
  'bar',
  'http://example.com/img1.jpg',
  'baz',
  'http://example.com/img2.jpg'
]

我在反应式思维方式中面临的主要问题是:如何根据某些条件设置一个可能必须在其中包含另一个可观察对象(或简单请求)的可观察对象?你将如何以优雅的反应方式做到这一点?

标签: typescriptrxjstwilio

解决方案


更改mapflatMap和不subscribe内部运算符,flatMap将为您执行内部可观察

          flatMap(data => data.items), 
          flatMap((item: any) => {
            return (item.type === 'media')? from(item.media.getContentUrl()):
            of(item.body);
          })

还有一个iif可用的运算符 https://www.learnrxjs.io/operators/conditional/iif.html

但我个人坚持使用原生 javascript


推荐阅读