如何从异步表达式中提前 return
How to early return from async expression
loadCustomer 有一个 return 类型的 Async<Result<Customer, string>>
,我只想在调用 loadCustomer 没有 return 错误时执行 loadData。如何在不使用第三方 asyncResult
表达式或自己编写的情况下实现此目的?
let getCustomerNameAndAmount customerId dataId =
async {
let! customer = loadCustomer customerId
let! data = loadData dataId
return customer |> Result.bind (fun c -> Ok (getNameOfCustomer c, data.Amount))
}
您缺少的操作是('a -> Async<Result<'b, 'e>>) -> Result<'a, 'e> -> Async<Result<'b, 'e>>
这可以写成:
let asyncResultBind<'a, 'b, 'e> (f : 'a -> Async<Result<'b, 'e>>) (a : Result<'a, 'e>) : Async<Result<'b, 'e>> =
match a with
| Ok v -> f v
| Error x -> async {return Error x}
现在您可以将 getCustomerNameAndAmount 写为:
let getCustomerNameAndAmount customerId dataId =
async {
let! customer = loadCustomer customerId
return! asyncResultBind
(fun c ->
async {
let! data = loadData dataId
return Ok (getNameOfCustomer c, data.Amount)
}
)
customer
}
当然也可以写成inline,不用抽象asyncResultBind
:
let getCustomerNameAndAmount customerId dataId =
async {
match! loadCustomer customerId with
|Ok c ->
let! data = loadData dataId
return Ok (getNameOfCustomer c, data.Amount)
|Error e ->
return Error e
}
loadCustomer 有一个 return 类型的 Async<Result<Customer, string>>
,我只想在调用 loadCustomer 没有 return 错误时执行 loadData。如何在不使用第三方 asyncResult
表达式或自己编写的情况下实现此目的?
let getCustomerNameAndAmount customerId dataId =
async {
let! customer = loadCustomer customerId
let! data = loadData dataId
return customer |> Result.bind (fun c -> Ok (getNameOfCustomer c, data.Amount))
}
您缺少的操作是('a -> Async<Result<'b, 'e>>) -> Result<'a, 'e> -> Async<Result<'b, 'e>>
这可以写成:
let asyncResultBind<'a, 'b, 'e> (f : 'a -> Async<Result<'b, 'e>>) (a : Result<'a, 'e>) : Async<Result<'b, 'e>> =
match a with
| Ok v -> f v
| Error x -> async {return Error x}
现在您可以将 getCustomerNameAndAmount 写为:
let getCustomerNameAndAmount customerId dataId =
async {
let! customer = loadCustomer customerId
return! asyncResultBind
(fun c ->
async {
let! data = loadData dataId
return Ok (getNameOfCustomer c, data.Amount)
}
)
customer
}
当然也可以写成inline,不用抽象asyncResultBind
:
let getCustomerNameAndAmount customerId dataId =
async {
match! loadCustomer customerId with
|Ok c ->
let! data = loadData dataId
return Ok (getNameOfCustomer c, data.Amount)
|Error e ->
return Error e
}