Swift F#异步HTTP请求-解析JSON响应

Swift F#异步HTTP请求-解析JSON响应,swift,rest,asynchronous,f#,http-post,Swift,Rest,Asynchronous,F#,Http Post,我正试图使用下面的F#片段向Firebase发送一个异步POST请求:特别是以下操作,它允许匿名登录: 我对F 35;非常陌生,对它的工作原理有点困惑。如何从该请求中获取JSON响应?我怎么知道这是什么时候完成的?这会阻止主线程上的UI吗?我正在翻译以下Swift代码块: Auth.auth().signInAnonymously(completion: { (user, error) in if let err = error { print(er

我正试图使用下面的
F#
片段向Firebase发送一个异步POST请求:特别是以下操作,它允许匿名登录:

我对F 35;非常陌生,对它的工作原理有点困惑。如何从该请求中获取JSON响应?我怎么知道这是什么时候完成的?这会阻止主线程上的UI吗?我正在翻译以下Swift代码块:

 Auth.auth().signInAnonymously(completion: { (user, error) in

        if let err = error {
            print(err.localizedDescription)
            return
        }

    })
这里的一切对我来说都是有意义的,因为我们有一个完成块,它在方法执行完毕后被调用,而且我们知道
user
变量将包含从服务器获得的响应,在F#中,它对我来说意义不大

更新:

根据评论中的建议,我引用了F#Data:HTTP实用程序,并创建了以下代码段:

let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX"
Http.RequestString
    ( url, 
      headers = [ ContentType HttpContentTypes.Json ],
      body = TextRequest """ {"returnSecureToken": true} """)
但是,这会产生错误
未定义值、命名空间、类型或模块Http

更新2: 我已接受以下代码:

let fetchUrl callback url (requestBody : string) =        
    let req = WebRequest.Create(Uri(url)) 
    req.Method <- "POST"
    let postBytes = requestBody |> System.Text.Encoding.ASCII.GetBytes
    req.ContentLength <- postBytes.LongLength
    req.ContentType <- "application/json; charset=utf-8"
    let reqStream = req.GetRequestStream() 
    reqStream.Write(postBytes, 0, postBytes.Length);
    reqStream.Close()

    use resp = req.GetResponse() 
    use stream = resp.GetResponseStream() 
    use reader = new IO.StreamReader(stream) 
    callback reader url

let myCallback (reader:IO.StreamReader) url = 
    let html = reader.ReadToEnd()
    let html1000 = html.Substring(0,1000)
    printfn "Downloaded %s. First 1000 is %s" url html1000
    html      // return all the html


let openLandlord ()  =
    let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXXXXXXXXX"
    let requestBody = """ {"returnSecureToken": true} """
    fetchUrl myCallback url requestBody
我得到以下错误:

此表达式应具有uint类型,但此处具有string类型

错误:

  • 绑定中此点或之前的不完整结构化构造
  • 未定义构造函数请求的值
  • 成员定义中存在意外的关键字匹配
  • 未定义值、命名空间、类型或模块响应
  • 成员定义中标识了意外的
    检查以下代码:

    open System
    open System.Net
    open FSharp.Data
    
    type Response = JsonProvider<""" { "name":"John", "age":94 } """>
    
    [<EntryPoint>]
    let main argv =
      let request () =
        async {
          let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX"
          return! Http.AsyncRequestString
            ( url,
              headers = [ "Content-Type", HttpContentTypes.Json ],
              body = TextRequest """ {"returnSecureToken": true} """ )
        } |>  Async.Catch
      let result = request ()
                   |> Async.RunSynchronously
      match result with
      | Choice1Of2 text -> let json = Response.Parse text
                           printfn "name: %A" json.Name   
      | Choice2Of2 e -> printfn "request failed: %A" e
      0 // return an integer exit code
    
    开放系统
    开放系统.Net
    打开FSharp.Data
    类型Response=JsonProvider
    []
    让主argv=
    让请求()=
    异步的{
    让url=”https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX"
    return!Http.AsyncRequestString
    (网址:,
    headers=[“内容类型”,HttpContentTypes.Json],
    body=TextRequest”“{“returnSecureToken”:true}”“)
    }|>Async.Catch
    让结果=请求()
    |>异步运行
    匹配结果
    |选择1of2 text->let json=Response.Parse text
    printfn“名称:%A”json.name
    |Choice2Of2 e->printfn“请求失败:%A”e
    0//返回整数退出代码
    
    如果提供的类型不适用于您的设置,这可能会有帮助:


    将示例JSON替换为服务的预期内容。

    您的问题太宽泛了。将一个高级API与另一个低级API进行比较。如果需要,可以将请求处理委托给库。例如,FSharp.Data有很好的HTTP实用程序:我不认为它太宽……我所要做的就是在不阻塞UI的情况下异步发送HTTP POST请求,然后在闭包块(或与之等效的东西)中获取此请求的JSON响应。我尝试过使用Http.fs,但是它显然不会安装在Xamariios上。很抱歉,我只是读到“这是如何工作的有点困惑”,这鼓励我详细解释代码,这需要太宽泛的答案。如果您只想从响应数据中获取JSON,可以使用FSharp.data或.NET Newtonsoft.JSON中特定于F#的JSON类型提供程序。两者都有很多例子。如果你使用异步操作,UI线程就可以了。不用担心@AlexAtNet,你能看看编辑吗?我已经尝试了从FSharp.Data链接中遵循POST示例。您可以使用AsyncRequestString异步获取字符串。要将Http导入作用域,您可以在代码文件的开头使用“open FSharp.Data”(就像在Swift中导入)。我知道,问题是我无法让您的代码在iOS设置中工作,我必须在其中构建此设置,而且我对F#非常陌生,不太了解代码中的控制流以及如何使用它,我不想简单地复制粘贴一些我无法理解的东西。。。然而,代码要简单得多,我理解它是如何工作的。我认为
    type
    语句应该从
    let
    中移出一级。是的,这很有帮助,问题是我仍然不能使用FSharp.Data。。。尽管我通过数据包管理器添加了它,并添加了open语句,但它似乎没有被识别。有没有不使用FSharp.Data的方法可以做到这一点?您是否尝试添加fsc.props以启用类型提供程序?您也可以使用Newtonsoft.Json,这是.net中Json的事实标准。@AlexNetkachov,看起来您在格式化字符串后漏掉了一个逗号:
    printfn“name:%a”Json.name
    let fetchUrl callback url (requestBody : string) =        
        let req = WebRequest.Create(Uri(url)) 
        req.Method <- "POST"
        let postBytes = requestBody |> System.Text.Encoding.ASCII.GetBytes
        req.ContentLength <- postBytes.LongLength
        req.ContentType <- "application/json; charset=utf-8"
        let reqStream = req.GetRequestStream() 
        reqStream.Write(postBytes, 0, postBytes.Length);
        reqStream.Close()
    
        use resp = req.GetResponse() 
        use stream = resp.GetResponseStream() 
        use reader = new IO.StreamReader(stream) 
        callback reader url
    
    let myCallback (reader:IO.StreamReader) url = 
        let html = reader.ReadToEnd()
        let html1000 = html.Substring(0,1000)
        printfn "Downloaded %s. First 1000 is %s" url html1000
        html      // return all the html
    
    
    let openLandlord ()  =
        let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXXXXXXXXX"
        let requestBody = """ {"returnSecureToken": true} """
        fetchUrl myCallback url requestBody
    
     override x.ViewDidLoad () =
        base.ViewDidLoad ()
        openLandlord ()
    
    open System
    open System.Net
    open FSharp.Data
    
    type Response = JsonProvider<""" { "name":"John", "age":94 } """>
    
    [<EntryPoint>]
    let main argv =
      let request () =
        async {
          let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX"
          return! Http.AsyncRequestString
            ( url,
              headers = [ "Content-Type", HttpContentTypes.Json ],
              body = TextRequest """ {"returnSecureToken": true} """ )
        } |>  Async.Catch
      let result = request ()
                   |> Async.RunSynchronously
      match result with
      | Choice1Of2 text -> let json = Response.Parse text
                           printfn "name: %A" json.Name   
      | Choice2Of2 e -> printfn "request failed: %A" e
      0 // return an integer exit code