我无法让 reqwest 板条箱在重用同一个客户端时执行一堆异步请求。如果我不使用客户端而只使用提供的get
界面,那么一切正常。本质上,我只是获取项目列表,然后使用异步获取列表中的所有内容。
但是,当我将客户端传递给我的get_object
闭包时,编译器会抱怨该引用需要静态生命周期,并且比“客户端”还要长。
我如何成功地注释这一生?还是有更好的方法来完成我想要的?
extern crate futures; // 0.3.1
extern crate reqwest; // 0.10.1
extern crate serde; // 1.0.104
extern crate serde_json; // 1.0.45
extern crate tokio; // 0.2.10
use serde::Deserialize;
use tokio::task;
#[derive(Debug, Deserialize)]
struct Item {
name: Option<String>,
id: Option<u64>,
}
pub trait ApiObject: Send {
type Uri;
fn from_json(text: &str) -> Result<Self, &'static str>
where
Self: Sized;
fn url(uri: Self::Uri) -> String;
}
impl ApiObject for Item {
type Uri = u64;
fn from_json(text: &str) -> Result<Item, &'static str> {
match serde_json::from_str::<Item>(text) {
Result::Ok(val) => Ok(val),
Result::Err(err) => match err.classify() {
serde_json::error::Category::Data => Err("json input semantically incorrect"),
serde_json::error::Category::Io => Err("failure to read/write bytes to io stream"),
serde_json::error::Category::Syntax => Err("json input not syntactically valid"),
serde_json::error::Category::Eof => Err("json data ended unexpectedly"),
},
}
}
fn url(uri: Self::Uri) -> String {
format!("http://cats.com/items/{}.json", uri.to_string())
}
}
/// Access point for any object inside the hybrid api
pub async fn get_object<O: 'static + ApiObject>(
uri: O::Uri,
client: &reqwest::Client,
) -> Result<O, &'static str> {
let url = O::url(uri);
let res = client.get(&url).send().await.unwrap();
match res.status() {
reqwest::StatusCode::OK => {
let text = res.text().await.unwrap();
task::spawn_blocking(move || to_struct(&text))
.await
.unwrap()
}
_ => Err("Request failed"),
}
}
#[tokio::main]
async fn main() {
let client = reqwest::Client::builder().build().unwrap();
let top: Vec<u64> = vec![1, 2, 3, 4, 5];
let futures: Vec<_> = top
.iter()
.map(|uri| get_object::<Item>(*uri, &client))
.collect();
let handles: Vec<_> = futures.into_iter().map(tokio::task::spawn).collect();
let results = futures::future::join_all(handles).await;
for result in results {
let x = result.unwrap().unwrap();
println!("{:#?}", x.name.unwrap());
}
}
fn to_struct<T: ApiObject>(text: &str) -> Result<T, &'static str> {
T::from_json(text)
}
错误信息:
error[E0597]: `client` does not live long enough
--> src/main.rs:73:46
|
73 | .map(|uri| get_object::<Item>(*uri, &client))
| ----- --------------------------^^^^^^-
| | | |
| | | borrowed value does not live long enough
| | returning this value requires that `client` is borrowed for `'static`
| value captured here
...
84 | }
| - `client` dropped here while still borrowed
它不同于如何使用 reqwest 执行并行异步 HTTP GET 请求?因为我使用闭包来传递客户端——使用async move
块似乎对我没有帮助