如何从返回未来的Rust函数中早日返回?

时间:2018-11-30 04:44:41

标签: asynchronous rust future

我有一个Rust函数,该函数接受输入URL,获取一些JSON,并返回带有已解析输出的Future。这是函数:

pub fn get<Output>(node: &str, path: &str) -> impl Future<Item = Output, Error = crate::Error>
where
    Output: for<'a> Deserialize<'a>,
{
    let mut opts = RequestInit::new();
    opts.method("GET");
    opts.mode(RequestMode::Cors);

    let mut url = node.to_owned();
    url.push_str(path);
    let request = Request::new_with_str_and_init(url.as_str(), &opts).unwrap();

    let window = web_sys::window().unwrap();
    let request_promise = window.fetch_with_request(&request);

    JsFuture::from(request_promise)
        .and_then(|resp_value| {
            assert!(resp_value.is_instance_of::<Response>());
            let resp = resp_value.dyn_into::<Response>().unwrap();
            resp.json()
        })
        .and_then(|json_value: Promise| {
            JsFuture::from(json_value)
        })
        .and_then(|json| {
            let out = json.into_serde::<Output>().unwrap();
            future::ok(out)
        })
        .map_err(crate::Error::JsError)
}

我想替换.unwrap()调用以尽早返回正确的错误,以使该函数不会出现混乱。这是我尝试过的类似功能:

pub fn post<Output, Params>(
    node: &str,
    path: &str,
    params: Params,
) -> impl Future<Item = Output, Error = crate::Error>
where
    Output: for<'a> Deserialize<'a>,
    Params: Serialize,
{
    let mut opts = RequestInit::new();
    opts.method("POST");
    opts.mode(RequestMode::Cors);

    match ::serde_json::to_string(&params) {
        Ok(s) => opts.body(Some(&JsValue::from_str(s.as_str()))),
        Err(error) => return future::err(Error::BadRequestJson(error)),
    };

    let mut url = node.to_owned();
    url.push_str(path);
    let request = match Request::new_with_str_and_init(url.as_str(), &opts) {
        Ok(r) => r,
        Err(_) => return future::err(Error::BadRequest),
    };

    let window = web_sys::window().unwrap();
    let request_promise = window.fetch_with_request(&request);

    JsFuture::from(request_promise)
        .and_then(|resp_value| {
            assert!(resp_value.is_instance_of::<Response>());
            let resp = resp_value.dyn_into::<Response>().unwrap();
            resp.json()
        })
        .and_then(|json_value: Promise| {
            JsFuture::from(json_value)
        })
        .and_then(|json| {
            let info = json.into_serde::<Output>().unwrap();
            future::ok(info)
        })
        .map_err(crate::Error::JsError)
}

但是Rust编译器不喜欢这样,因为返回了两种不同的类型:

error[E0308]: mismatched types

   |
75 | /     JsFuture::from(request_promise)
76 | |         .and_then(|resp_value| {
77 | |             // `resp_value` is a `Response` object.
78 | |             assert!(resp_value.is_instance_of::<Response>());
...  |
92 | |         })
93 | |         .map_err(crate::Error::JsError)
   | |_______________________________________^ expected struct `futures::future::result_::FutureResult`, found struct `futures::future::map_err::MapErr`
   |
   = note: expected type `futures::future::result_::FutureResult<Output, error::Error>`
              found type `futures::future::map_err::MapErr<futures::future::and_then::AndThen<futures::future::and_then::AndThen<futures::future::and_then::AndThen<wasm
_bindgen_futures::JsFuture, std::result::Result<js_sys::Promise, wasm_bindgen::JsValue>, 

那么可以在不更改返回类型的情况下从此函数提前返回吗?我知道我可以将返回类型更改为Result,但这似乎不必要。

0 个答案:

没有答案