F# Fable Fetch 正确地将 Promise 解包到另一个 Promise 类型
F# Fable Fetch Correctly Unwrap Promise to another Promise type
我需要从多个 URL 请求数据,然后使用结果。
我正在使用带有 Fable-Promise 和 Fable-Fetch 库的纯寓言 3。
我已经弄清楚了如何从多个 URL 中获取并将结果组合成一个 Promise,然后我可以用它来更新 UI(多个结果只需要绘制一次)。
但是,如果其中一个提取错误,那么整个事情都会失败。理想情况下,我想使用 tryFetch
然后传播 Result<TermData, None | Exception>
但我似乎没有做任何编译。
我究竟如何使用 tryFetch
然后在 CE 中用第二个 let!
解包结果? (评论说明更多)
module App
open Browser.Dom
open App
open System.Collections.Generic
open System.Text.RegularExpressions
open Fetch
open System
type TermData =
abstract counts : int []
abstract scores : int []
abstract term : string
abstract allWords : bool
type QueryTerm =
{ mutable Term: string
mutable AllWords: bool }
let loadSingleSeries (term: QueryTerm) =
promise {
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
// Works but doesn't handle errors.
let! plotData = fetch url [] // type of plotData: Response
// let plotDataResult = tryFetch url []
// This ideally becomes Promise<Result<TermData, None>>
// let unwrapped = match plotDataResult with
// | Ok res -> Ok (res.json<TermData>()) // type: Promise<TermData>
// | Error err -> ??? // tried Error (Promise.create(fun resolve reject -> resolve None)) among others
let! result = plotData.json<TermData>() // type of result: TermData
return result
}
let dataArrays =
parsed // type Dictionary<int, TermData>
|> Seq.map (fun term -> loadSingleSeries term.Value)
|> Promise.Parallel
|> Promise.map (fun allData -> console.log(allData))
// Here we will handle None when we have it
我没有太多 Fable 经验,但如果我正确理解你的问题,我认为以下内容应该有效:
let loadSingleSeries (term: QueryTerm) =
promise {
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
let! plotDataResult = tryFetch url []
match plotDataResult with
| Ok resp ->
let! termData = resp.json<TermData>()
return Ok termData
| Error ex ->
return Error ex
}
这里的想法是,如果您遇到错误,您只需在新的 Result
值中传播该错误。这 return 是 Promise<Result<TermData, Exception>>
,正如您所要求的。
更新:使用第二个 let!
.
修复了 return 类型
我没有 运行 这段代码,但查看文档看起来你需要使用 Promise.catch
let loadSingleSeries (term: QueryTerm) =
promise {
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
let! plotDataResult =
fetch url []
|> Promise.map Ok // Wraps the "happy path" in a Result.Ok
|> Promise.catch (fun err ->
//handle the error
Error err)
return
match plotDataResult with
| Ok res -> ...
| Error err -> ...
}
我最终不得不为此使用管道而不是 CE 方法,如下所示:
let loadSingleSeries (term: QueryTerm) =
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
let resultPromise =
fetch url []
|> Promise.bind (fun response ->
let arr = response.json<TermData> ()
arr)
|> Promise.map (Ok)
|> Promise.catch (Error)
resultPromise
关键是使用 Promise.bind
将获得 Response
的第一个承诺转换为 Promise<TermData>
的承诺。 map
和 catch
然后转换为 Promise<Result<TermData, exn>>
.
我需要从多个 URL 请求数据,然后使用结果。
我正在使用带有 Fable-Promise 和 Fable-Fetch 库的纯寓言 3。
我已经弄清楚了如何从多个 URL 中获取并将结果组合成一个 Promise,然后我可以用它来更新 UI(多个结果只需要绘制一次)。
但是,如果其中一个提取错误,那么整个事情都会失败。理想情况下,我想使用 tryFetch
然后传播 Result<TermData, None | Exception>
但我似乎没有做任何编译。
我究竟如何使用 tryFetch
然后在 CE 中用第二个 let!
解包结果? (评论说明更多)
module App
open Browser.Dom
open App
open System.Collections.Generic
open System.Text.RegularExpressions
open Fetch
open System
type TermData =
abstract counts : int []
abstract scores : int []
abstract term : string
abstract allWords : bool
type QueryTerm =
{ mutable Term: string
mutable AllWords: bool }
let loadSingleSeries (term: QueryTerm) =
promise {
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
// Works but doesn't handle errors.
let! plotData = fetch url [] // type of plotData: Response
// let plotDataResult = tryFetch url []
// This ideally becomes Promise<Result<TermData, None>>
// let unwrapped = match plotDataResult with
// | Ok res -> Ok (res.json<TermData>()) // type: Promise<TermData>
// | Error err -> ??? // tried Error (Promise.create(fun resolve reject -> resolve None)) among others
let! result = plotData.json<TermData>() // type of result: TermData
return result
}
let dataArrays =
parsed // type Dictionary<int, TermData>
|> Seq.map (fun term -> loadSingleSeries term.Value)
|> Promise.Parallel
|> Promise.map (fun allData -> console.log(allData))
// Here we will handle None when we have it
我没有太多 Fable 经验,但如果我正确理解你的问题,我认为以下内容应该有效:
let loadSingleSeries (term: QueryTerm) =
promise {
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
let! plotDataResult = tryFetch url []
match plotDataResult with
| Ok resp ->
let! termData = resp.json<TermData>()
return Ok termData
| Error ex ->
return Error ex
}
这里的想法是,如果您遇到错误,您只需在新的 Result
值中传播该错误。这 return 是 Promise<Result<TermData, Exception>>
,正如您所要求的。
更新:使用第二个 let!
.
我没有 运行 这段代码,但查看文档看起来你需要使用 Promise.catch
let loadSingleSeries (term: QueryTerm) =
promise {
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
let! plotDataResult =
fetch url []
|> Promise.map Ok // Wraps the "happy path" in a Result.Ok
|> Promise.catch (fun err ->
//handle the error
Error err)
return
match plotDataResult with
| Ok res -> ...
| Error err -> ...
}
我最终不得不为此使用管道而不是 CE 方法,如下所示:
let loadSingleSeries (term: QueryTerm) =
let url =
$"/api/plot/{term.Term}?allWords={term.AllWords}"
let resultPromise =
fetch url []
|> Promise.bind (fun response ->
let arr = response.json<TermData> ()
arr)
|> Promise.map (Ok)
|> Promise.catch (Error)
resultPromise
关键是使用 Promise.bind
将获得 Response
的第一个承诺转换为 Promise<TermData>
的承诺。 map
和 catch
然后转换为 Promise<Result<TermData, exn>>
.