【发布时间】:2017-12-27 15:56:19
【问题描述】:
我正在尝试使用F# 的以下 sn-p 向 Firebase 发送异步 POST 请求:特别是以下允许匿名登录的操作:
https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-anonymously
let makePostRequest (url : string) (requestBody : string) =
let req = WebRequest.CreateHttp url
req.CookieContainer <- new CookieContainer()
req.Method <- "POST"
req.ProtocolVersion <- HttpVersion.Version10
let postBytes = requestBody |> System.Text.Encoding.ASCII.GetBytes
req.ContentLength <- postBytes.LongLength
req.ContentType <- "application/xml; charset=utf-8"
async{
use! reqStream = req.GetRequestStreamAsync() |> Async.AwaitTask
do! reqStream.WriteAsync(postBytes, 0, postBytes.Length) |> Async.AwaitIAsyncResult |> Async.Ignore
reqStream.Close()
use! res = req.AsyncGetResponse()
use stream = res.GetResponseStream()
use reader = new StreamReader(stream)
let! rdata = reader.ReadToEndAsync() |> Async.AwaitTask
return rdata
}
我这样称呼它:
let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXXXXXXX"
let data = "returnSecureToken=true"
makePostRequest url data
我对@987654329@ 很陌生,对它的工作原理有点困惑。如何从该请求中获取 JSON 响应?我怎么知道这何时完成?这会阻塞主线程上的 UI 吗?我正在做的是翻译以下 Swift 代码块:
Auth.auth().signInAnonymously(completion: { (user, error) in
if let err = error {
print(err.localizedDescription)
return
}
})
这里的一切对我来说都很有意义,因为我们有一个完成块,在方法执行完成后会调用它,并且我们知道 user 变量将包含从服务器获得的响应,这对我来说意义不大在 F# 中。
更新:
按照 cmets 中的建议,我参考了 F# Data: HTTP Utilities 并创建了以下代码 sn-p:
let url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=XXXXXXXXXXXX"
Http.RequestString
( url,
headers = [ ContentType HttpContentTypes.Json ],
body = TextRequest """ {"returnSecureToken": true} """)
但是这会产生错误The value, namespace, type or module Http is not defined
更新 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
按照这里的例子:
https://fsharpforfunandprofit.com/posts/fvsc-download/
但是,当我在这里调用 openLandlord 函数时:
override x.ViewDidLoad () =
base.ViewDidLoad ()
openLandlord ()
我收到以下错误:
此表达式应为 uint 类型,但此处为 string 类型。
错误:
- 在此绑定点或之前的不完整结构化构造。
- 构造函数请求的值未定义。
- 成员定义中出现意外的关键字匹配。
- 未定义值、命名空间、类型或模块响应。
- 在成员定义中发现了意外。
【问题讨论】:
-
你的问题太宽泛了。并且您将一个高级 API 与另一个低级 API 进行比较。如果需要,您可以将请求处理委托给库。例如,FSharp.Data 有很好的 HTTP 实用程序:fsharp.github.io/FSharp.Data/library/Http.html
-
我觉得不会太宽泛...我要做的就是在不阻塞UI的情况下异步发送一个HTTP POST请求,然后在一个闭包块中获取这个请求的JSON响应(或与之等效的东西)。我尝试使用 Http.fs 但这显然不会为 xamarinios 安装
-
抱歉,我只是读到“对它的工作原理有点困惑”,因为它鼓励我详细解释代码,这需要太宽泛的答案。如果您只想从响应数据中获取 JSON,则可以使用来自 FSharp.Data 或 .NET Newtonsoft.JSON 的 F# 特定 JSON 类型提供程序。两者都有很多例子。如果您使用异步操作,UI 线程会很好。
-
不用担心@AlexAtNet,你能看看编辑吗?我尝试按照您链接的 FSharp.Data 中的 POST 示例进行操作
-
您可以使用 AsyncRequestString 异步获取字符串。要将 Http 导入作用域,您可以在代码文件的开头使用“open FSharp.Data”(类似于 Swift 中的导入)。
标签: swift rest asynchronous f# http-post