我正在使用sttp客户端。我想将响应解释为以行分隔的字符串,例如Observable[String]
这里是sttp流式API:
import java.nio.ByteBuffer
import com.softwaremill.sttp._
import com.softwaremill.sttp.okhttp.monix.OkHttpMonixBackend
import monix.eval.Task
import monix.reactive.Observable
implicit val sttpBackend = OkHttpMonixBackend()
val res: Task[Response[Observable[ByteBuffer]]] = sttp
.post(uri"someUri")
.response(asStream[Observable[ByteBuffer]])
.send()
那么我如何获得Observable[String]
?
这里有一些想法:
1。。有没有一种简单的方法可以split
通过行进行观察?
2。也许我可以从响应中获取原始的InputStream
,所以我可以轻松地拆分它,但是我找不到找到类似asStream[InputStream]
的方法的方法
3。还是只使用http后端sttp
层?
答案 0 :(得分:0)
您的基本问题是如何将Observable[ByteBuffer]
转换为Observable[String]
,其中每个String
是一行,对吗?
您可以使用方法bufferWithSelector(selector: Observable[S]): Observable[Seq[A]]
。
此方法将缓冲Observable,直到选择器Observable发出元素为止。
我使用Int
s做了一个小例子:
import monix.reactive.Observable
import monix.execution.Scheduler.Implicits.global
import scala.concurrent.duration._
val source = Observable.range(0, 1000, 1)
.delayOnNext(100.milliseconds)
val selector = source.filter(_ % 10 == 0)
val buffered = source.bufferWithSelector(selector)
.map(_.foldLeft("")((s, i) => s + i.toString)) // This folds the Seq[Int] into a String for display purposes
buffered.foreach(println)
当然,这有一个主要缺点:底层的Observable source
将被评估两次。您可以通过修改上面的示例来看到这一点:
// Start writing your ScalaFiddle code here
import monix.reactive.Observable
import monix.execution.Scheduler.Implicits.global
import scala.concurrent.duration._
val source = Observable.range(0, 1000, 1)
.delayOnNext(100.milliseconds)
.map {x => println(x); x} // <------------------
val selector = source.filter(_ % 10 == 0)
val buffered = source.bufferWithSelector(selector)
.map(_.foldLeft("")((s, i) => s + i.toString))
buffered.foreach(println)
这将对每个数字打印两次。
要解决此问题,您必须将source
Observable转换为热门Observable:
import monix.reactive.Observable
import monix.execution.Scheduler.Implicits.global
import scala.concurrent.duration._
val source = Observable.range(0, 1000, 1)
.delayOnNext(100.milliseconds)
.map {x => println(x); x}
.publish // <-----------------------------
// source is now a ConnectableObservable and will start emitting elements
// once you call source.connect()
val selector = source.filter(_ % 10 == 0)
val buffered = source.bufferWithSelector(selector)
.map(_.foldLeft("")((s, i) => s + i.toString))
buffered.foreach(println)
source.connect() // <---------------------------
您唯一需要做的就是修改选择器以仅发出项目 遇到换行时。
我建议先(使用Observable[ByteBuffer]
将Observable[Byte]
分成flatMap
以避免头痛。