Я не понимаю, как синтаксис async
/ await
категорически поможет вам с Either
.В конечном итоге вам все еще нужно возвращать один конкретный тип, и это то, что обеспечивает Either
.async
/ await
уменьшит потребность в комбинаторах, таких как Future::map
или Future::and_then
однако.
См. Также:
При этом вам не нужно использовать Either
здесь.
У вас есть последовательные Result
-возврат функций, так что вы можете позаимствовать уловку из JavaScript и использовать IIFE , чтобы использовать оператор ?
.Затем мы можем «поднять» объединенный Result
в будущее и связать его с будущим от получателя:
fn deferred_task() -> impl Future<Item = i32, Error = MyError> {
let (tx, rx) = oneshot::channel();
let x = (|| {
let _i = query_data().map_err(|_| MyError { error_code: 1 })?;
send_promise_to_worker(tx).map_err(|_| MyError { error_code: 2 })?;
Ok(())
})();
future::result(x).and_then(|()| rx.map_err(MyError::from))
}
В будущем этот IIFE может быть заменен блоком try
, насколько я понимаю.
Вы также можете пойти другим путем и преобразовать все в будущее:
fn deferred_task() -> impl Future<Item = i32, Error = MyError> {
let (tx, rx) = oneshot::channel();
query_data()
.map_err(|_| MyError { error_code: 1 })
.into_future()
.and_then(|_i| {
send_promise_to_worker(tx)
.map_err(|_| MyError { error_code: 2 })
.into_future()
})
.and_then(|_| rx.map_err(MyError::from))
}
Этот поможет с async
/Синтаксис await
:
async fn deferred_task() -> Result<i32, MyError> {
let (tx, rx) = oneshot::channel();
query_data().map_err(|_| MyError { error_code: 1 })?;
send_promise_to_worker(tx).map_err(|_| MyError { error_code: 2 })?;
let v = await! { rx }?;
Ok(v)
}
Я также видел улучшенный синтаксис для построения Either
путем добавления left
и right
методов к признаку Future
:
foo.left();
// vs
Either::left(foo);
Однако это не отображается ни в одной из текущих реализаций.
A Future
равно a Result
Нет, это не.
Есть два соответствующих Future
s, о которых можно поговорить:
В частности, Future::poll
возвращает тип, который может находиться в двух состояниях:
В ящике с фьючерсами «успех» и «провал» привязаны к «завершению», тогда как в стандартной библиотеке - нет.В ящике Result
реализуется IntoFuture
, а в стандартной библиотеке вы можете использовать future::ready
.Оба из них позволяют конвертировать Result
в будущее, но это не значит, что Result
- это будущее, не более, чем утверждение, что Vec<u8>
- итератор, даже если он можетможно преобразовать в единицу.
Возможно, что оператор ?
(питается от черты Try
) будет расширен для автоматического преобразования из Result
в определенный тип Future
, иличто Result
даже реализует Future
напрямую, но я не слышал ни о каких таких планах.