Как разблокировать будущую ветку и вернуть результаты - PullRequest
0 голосов
/ 07 октября 2019

Я решил использовать гипер-создание для создания сервера, который считывает данные тела метода POST. Как мне синхронно вернуть значение, рассчитанное в асинхронном будущем в стабильном Rust? объясняет часть того, что я ищу, но я не хочу использовать tokio::run или future::lazy, потому что согласноВ моем понимании гипер использует Tokio и futures, а гипертело возвращает поток. Я пытаюсь найти другие способы обработки потока и получить больше знаний о гипер Request методах.

В первом подходе я concat2 затем вызываю wait. wait блокирует текущий поток, поэтому мой код зависает.

if Method::POST == req.method() {
    let body = req.into_body().concat2().wait();
    // convert to json and do something with the data.
    Ok(Response::new(Body::from("OK: data submitted")))
}

Во втором подходе я попытался использовать poll и and_then, но я всегда получаю NotReady. Тип результата: futures::poll::Async<hyper::Chunk>.

if Method::POST == req.method() {
    let body = req.into_body().concat2().poll().and_then(|e| {
        // do something
        Ok(e)
    });

    match body {
        Ok(e) => println!("{:#?}", e),
        Err(r) => println!("{:#?}", r),
    };
    Ok(Response::new(Body::from("")))
}
  1. Как разблокировать текущий поток и вернуть результаты?
  2. Как я могу опросить, а затем вернуть результаты,?

Если возможно, пожалуйста, объясните, как правильно обращаться с futures::poll::Async и wait(). На данный момент async / await нестабильно в Rust, поэтому я не могу его использовать.

1 Ответ

1 голос
/ 07 октября 2019

Как я уверен, вы обнаружили, что вызов wait() для фьючерсов является анти-паттерном и в целом побеждает цель асинхронного ввода-вывода (поскольку вы блокируете свой поток - и, следовательно,executor - делает это).

hyper Маршруты принимают возврат, который реализует IntoFuture, тип, реализованный для Option<T> и Result<T, E> общим способом. Таким образом, то, что вы на самом деле написали, вообще не нужно блокировать - вам просто нужно объединить фьючерсы следующим образом:

if Method::POST == req.method() {
   req.into_body().concat2().map(|_body| {
       Response::new(Body::from("OK: data submitted"))
   })
}

Вы даже не используете содержимое bodyв вашем коде, но я предполагаю, что это для целей MCVE. Внутри комбинатора map() это значение в настоящее время отображается как _body и позволяет вам делать с ним все, что вы хотите.

Я предполагаю, что вы оказались в этом углу из-за документации - все комбинаторынаходятся на объекте черты FutureExt;они не определены по признакам Future и Stream. В результате они не сразу всплывают при просмотре документа на 0,2 / 0,3, и, возможно, вам показалось, что ваши единственные доступные вызовы были poll_next() и wait().

...