在管理错误的同时在管道中链接异步rest调用 [英] chaining async rest calls in a pipeline while managing errors

查看:125
本文介绍了在管理错误的同时在管道中链接异步rest调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于先前基于同步的问题调用,在以下情况下如何处理异步方法.

Building on previous question based on synchronous calls, how do we approach asynchronous methodology in the following scenario.

let fetch1 (result: string) : Result<string, string> =
    try
        use request = WebRequest.Create("http://bing.com") :?> HttpWebRequest
        use response = request.GetResponse()
        use reader = new StreamReader(response.GetResponseStream())
        let html = reader.ReadToEnd()
        Ok "success"
    with
        | :? WebException as e ->
        Error "error with the url"

let fetch2 (result: string) : Result<string, string> =
    try
        use request = WebRequest.Create("http://google.com") :?> HttpWebRequest
        use response = request.GetResponse()
        use reader = new StreamReader(response.GetResponseStream())
        let html = reader.ReadToEnd()
        Ok "success"
    with
        | :? WebException as e ->
        Error "error with the url"

let fetch3 (result: string) : Result<string, string> =
     try
         use request = WebRequest.Create("http://invalid.com") :?> HttpWebRequest
         use response = request.GetResponse()
         use reader = new StreamReader(response.GetResponseStream())
         let html = reader.ReadToEnd()
         Ok "success"
     with
         | :? WebException as e ->
         Error "error with the url"

测试

let chain = fetch1 >> Result.bind fetch2 >> Result.bind fetch3

match chain("") with 
| Ok message -> Debug.WriteLine(message)
| Error error -> Debug.WriteLine(error)

尝试

let fetch1 (result: string) :Result<string, string> = async {
    try
        use! request = WebRequest.Create("http://bing.com") :?> HttpWebRequest
        use response = request.GetResponse()
        use reader = new StreamReader(response.GetResponseStream())
        let html = reader.ReadToEnd()
        Ok "success"
    with
        | :? WebException as e ->
        Error "error with the url"
 }

错误

该表达式的类型为'Result',但此处的类型为'Async<'a>'

This expression was epxected to have type 'Result' but here has type 'Async<'a>'

推荐答案

您应在此处说明您实际上试图实现的异常处理机制.在许多情况下,仅使用普通的F#内置异常会很好地工作.

You should explain what exception handling mechanism are you actually trying to implement here. For many things, using just normal F# built-in exceptions will work perfectly fine.

您正在使用Result.bind,这是一种实现异常处理行为的方法,其中,如果任何步骤引发异常,则总体计算将失败.这是您要达到的目标吗?如果是这样,您可以仅依靠内置的F#异步支持来处理异常,并在调用两个fetch函数的异步计算中包含try .. with.一个最小的例子:

You are using Result.bind which is a way to implement an exception handling behaviour where, if any step throws an exception, the overall computation will fail. Is this what you want to achieve? If so, you can just rely on built-in F# async support for exception handling and have try .. with in the async computation that calls the two fetch functions. A minimal example:

let fetch url = async {
  use wc = new WebClient()
  let! res = wc.AsyncDownloadString(System.Uri(url))
  return res }

let fetchAllOrNothing = async {
  try 
    let! goog = fetch "http://www.google.com"
    let! bing = fetch "http://www.bing.com"
    return Some(goog.Length, bing.Length)
  with _ ->
    return None }

如果您要调用所有提取函数,并且仅在所有它们都失败时才失败,那么您将需要使用异常处理程序包装单个fetch函数(如您所做的那样),然后选择第一个结果.使用普通的F#选项类型,可以使用Array.tryPick:

If you want to call all fetch functions and fail only if all of them fail, then you will need to wrap individual fetch functions with exception handlers (as you do) and then pick the first result. Using normal F# option type, this can be done using Array.tryPick:

let fetch url = async {
  try
    use wc = new WebClient()
    let! res = wc.AsyncDownloadString(System.Uri(url))
    return Some res 
  with _ -> 
    return None }

let fetchFirstOne = async {
  let! all = 
    [ fetch "http://www.google.com"
      fetch "http://www.bing.com" ] |> Async.Parallel
  return Array.tryPick (fun x -> x) all }

如果您从F#开始,那么开始使用诸如async核心功能和选项之类的东西就容易得多-一旦熟悉了这些功能和选项,就可以考虑使用更复杂的方法.

If you are starting with F#, then it is a lot easier to get started using things like core async functions and options - once you are comfortable with those, it makes sense to look at more sophisticated methods.

这篇关于在管理错误的同时在管道中链接异步rest调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆