F#:异步下载数据

MY_G

我是编程新手,F#是我的第一语言。

这是我的代码的相关部分:

open System.IO
open System.Net

let downloadHtmlFromUrlAsync (url: string) =
    async { 
        let uri = new System.Uri(url)
        let webClient = new WebClient()
        let! html = webClient.AsyncDownloadString(uri)
        return html
        }

let downloadHtmlToDisk (url: string) (directoryPath: string) = 
    if isValidUrl url then
        let name = getNameFromRedirectedUrl url
        let id = getIdFromUrl url
        let html = downloadHtmlFromUrlAsync url
        let newTextFile = File.Create(directoryPath + "\\" + id.ToString("00000") + " " + name.TrimEnd([|' '|]) + ".html")
        use file = new StreamWriter(newTextFile) 
        file.Write(html) 
        file.Close()

let downloadEntireDatabase (baseUrl: string) (totalNumberOfPeople: int) = 
    let allIds = [ for i in 1 .. totalNumberOfPeople -> i ]

    allIds
    |> Seq.map (fun id -> baseUrl + string(id))
    |> Seq.filter isValidUrl
    |> Seq.map downloadHtmlToDisk
    |> Async.Parallel 
    |> Async.RunSynchronously

我已经在F#交互中测试了功能isValidUrl,getNameFromRedirectedUrl,getIdFromUrl。他们工作正常。

我的问题是:当我尝试运行上面粘贴的代码时,会产生以下错误消息:

Program.fs(483,8):错误FS0193:类型约束不匹配。类型seq<(string -> unit)>与类型不兼容类型seq<Async<'a>>与类型Async<'a>不匹配string -> unit

什么地方出了错?我应该做些什么改变?

卡斯滕

问题可能出在这行(您能否给我们提供的定义downloadFighterHtmlToDisk):

  allIds
    ...
    |> Seq.map downloadFighterHtmlToDisk
    ...

根据错误消息,此功能似乎具有签名,string -> string -> unit但您确实需要string -> Async<'something>

现在,我猜您使用downloadHtmlToDisk了类似的东西,并且可以,但是我建议将其重写为:

let downloadHtmlToDisk (directoryPath: string) (url: string) = 
    async {
        if isValidUrl url then
            let name = getNameFromRedirectedUrl url
            let id = getIdFromUrl url
            let! html = downloadHtmlFromUrlAsync url
            let newTextFile = File.Create(directoryPath + "\\" + id.ToString("00000") + " " + name.TrimEnd([|' '|]) + ".html")
            use file = new StreamWriter(newTextFile) 
            file.Write(html) 
    }

并像这样使用

 let downloadEntireDatabase (baseUrl: string) (totalNumberOfPeople: int) = 
        let allIds = [ for i in 1 .. totalNumberOfPeople -> i ]

        allIds
        |> Seq.map (fun id -> (id, baseUrl + string(id)))
        |> Seq.filter (fun (_,url) -> isValidUrl url)
        |> Seq.map (fun (id,url) -> downloadHtmlToDisk (getFighterPath id) url)
        |> Async.Parallel 
        |> Async.RunSynchronously

看到let! html = ..吗?这很重要-这将是async要发生的事情;)-如果您愿意,可以找到类似的操作来异步写入文件。另外,您不需要关闭文件-处理应该处理它

评论

我刚刚看到您从URL中重新提取ID-您也可以使用此ID代替我使用元组的方式,但是我认为最好将ID传递给您,例如,downloadHtmlToDisk您确实需要IDid和可以urlid那里创建-一种更简单的IMO方法,但是我不想重写您所进行的一切–只是尝试一下

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章