Секвенирование двух независимых фьючерсов с разными типами ошибок - PullRequest
0 голосов
/ 21 сентября 2019

У меня есть код, приведенный ниже: -

let done = client_a.
    .get_future(data)
    .then(move |result| {
        // further processing on result
        spawn a future here.
    });

tokio::run(done);

Теперь у меня есть еще одно будущее, результат которого я хочу обработать вместе с «обработкой результата».Однако это будущее полностью не зависит от client_a, что подразумевает: -

  • оба могут иметь разные типы ошибок.
  • отказ одного не должен останавливать другого.

    let done = client_a.
        .get_future(data)
        .then(move |result| {
            // how to fit in 
            // client_b.get_future
            // here
    
            // further processing on both results
            spawn third future here.
        });
    
        tokio::run(done);
    

1 Ответ

1 голос
/ 21 сентября 2019

Если оба типа ошибок и типов элементов неоднородны, и вы знаете сколько фьючерсов вы объедините в цепочку, самый простой способ сделать это - создать непогрешимый Future (потому что это то, что на самом деле остается вашим будущим будущимis) тип Item которого является кортежем всех промежуточных результатов.

Это может быть относительно просто реализовано простым построением цепочки:

let future1_casted = future1.then(future::ok::<Result<_, _>, ()>);
let future2_casted = future2.then(future::ok::<Result<_, _>, ()>);

let chain = future1_casted
    .and_then(|result1| future2_casted.map(|result2| (result1, result2)));

ссылка на игровую площадку

Последний тип будущего - это кортеж, содержащий все результаты фьючерсов.

Если вы не знаете, сколько фьючерсов вы объединяете в цепочки, вам нужно будет усилить свои требования и четко знать заранеевремя возможные типы возврата вашего будущего.Поскольку без макроса невозможно создать кортеж произвольного размера, вам нужно будет сохранить промежуточные результаты в структуре, требующей однородных типов.

Чтобы решить эту проблему, определив кортежи, содержащие ваши типы,например, для ошибок, требуется:

#[derive(PartialEq, Debug)]
pub enum MyError {
    Utf16Error(char::DecodeUtf16Error),
    ParseError(num::ParseIntError)
}

impl From<char::DecodeUtf16Error> for MyError {
    fn from(e: char::DecodeUtf16Error) -> Self {
        MyError::Utf16Error(e)
    }
}

impl From<num::ParseIntError> for MyError {
    fn from(e: num::ParseIntError) -> Self {
        MyError::ParseError(e)
    }
}

Оттуда объединение фьючерсов идет по тому же маршруту, что и раньше - превратить ошибочное будущее в безошибочное возвращение Result<_, _>, а затем объединить в структуру, подобную Vec с future::loop_fn()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...