如何有效地以阻塞方式提取future :: Stream的第一个元素?

时间:2019-03-02 22:55:36

标签: stream rust

我有以下方法:

pub fn load_names(&self, req: &super::MagicQueryType) -> ::grpcio::Result<::grpcio::ClientSStreamReceiver<String>> {

我的目标是获得grpcio::ClientSStreamReceiver的第一个元素;我不在乎其他名称:

let name: String = load_names(query)?.wait().nth(0)?;

wait()之前调用nth(0)似乎效率不高,因为我相信wait()会阻塞流,直到接收到所有元素为止。

如何在不触发构建错误的情况下编写更有效的解决方案(即nth(0).wait())? Rust在futures::stream::Stream上的构建错误令我感到非常困惑。

Rust playground不支持grpcio = "0.4.4",因此我无法提供链接。

1 个答案:

答案 0 :(得分:2)

要以阻塞方式提取futures::Stream的第一个元素,应通过调用Stream::wait然后将Iterator::next转换为Stream到迭代器。阅读Stream::wait的文档说明,它基本上是最有效的实现:

  

如果流中的项目尚未准备就绪,则此迭代器将在每次调用next时阻止当前线程。

use futures::{stream, Stream}; // 0.1.25
use std::iter;

fn example() -> impl Stream<Item = i32, Error = ()> {
    stream::iter_ok(iter::repeat(42))
}

fn main() {
    let v = example().wait().next();
    println!("{:?}", v);
}

如果您使用的是Tokio,则可以将Stream转换为Future并致电Runtime::block_on

use std::iter;
use tokio::prelude::*; // 0.1.15

fn example() -> impl Stream<Item = i32, Error = ()> {
    stream::iter_ok(iter::repeat(42))
}

fn main() {
    let mut runtime = tokio::runtime::Runtime::new().expect("Unable to create a runtime");
    let r = runtime.block_on(example().into_future());
    if let Ok((v, _)) = r {
        println!("{:?}", v);
    }
}

另请参阅: