我有一个使用寓言elmish的模型更新视图架构的项目。我必须每分钟下载文件并读取这些文件。如何在更新功能中下载以及如何读取和解析为 Json?
我也需要使用寓言创建动态图表。有人知道怎么做?
我这里有我的部分代码:
let update (msg : Msg) (model : Model) =
match msg with
| GetData ->
model,
Cmd.ofPromise
(fun () ->
promise {
let wc = new WebClient()
wc.DownloadData("https://www.quandl.com/api/v1/datasets/LBMA/SILVER.json", "SILVER.json")
wc.DownloadData("https://www.quandl.com/api/v1/datasets/LBMA/GOLD.json", "GOLD.json")
// Read 2 files
// Return 2 Json.Object
})
()
(fun silver gold -> GotData silver gold)
(fun e -> GotError e.Message)
| GotData silver gold ->
(Model.SilverData silver, Model.GoldData gold), // I think this doesn't work
Cmd.ofPromise
(fun () -> Promise.sleep 60000)
()
(fun () -> GetData)
(fun e -> GetData)
如果你有一个周期性事件,应该在你的Elmish应用程序中引起一些操作,我会使用订阅。以下代码片段显示了一个函数,该函数设置一个间隔,该间隔导致每 10 分钟调度一次命令。
let timer initial =
let sub dispatch =
window.setInterval(fun _ -> dispatch LoadDataSet; console.log("Timer triggered")
, 1000 * 60 * 10) |> ignore
Cmd.ofSub sub
可以使用Program.withSubscription
函数将订阅添加到主调度循环。
我会使用Fable PowerPack包来获得fetch
,并promise
支持来获取数据集。以下代码将从指定的终结点提取文档,将它们分析为DataSet
类型的值,并在 promise 的成功路径上将它们作为SilverAndGold
模型类型的值返回。
type DataSet =
{ column_names : string list
data : (string * float * float * float) list }
type SilverAndGold =
{ Silver : DataSet
Gold : DataSet }
...
let fetchDataSets () = promise {
let! silverData = Fetch.fetchAs<DataSet> "https://www.quandl.com/api/v1/datasets/LBMA/SILVER.json" []
let! goldData = Fetch.fetchAs<DataSet> "https://www.quandl.com/api/v1/datasets/LBMA/GOLD.json" []
return { Silver = silverData; Gold = goldData }
}
在Elmish应用程序的更新功能中,您可以看到承诺执行是如何触发的。在我们的订阅发送的每条LoadDataSet
消息上,我们都会创建一个承诺命令,该命令要么导致包含数据集的DataSetLoaded
消息,要么导致错误。
let update (msg:Msg) (model:Model) =
match msg with
| LoadDataSet ->
model, Cmd.ofPromise fetchDataSets () DataSetLoaded Error
| DataSetLoaded silverGold ->
// here you could process you silver and gold datasets
console.log silverGold
Some silverGold, Cmd.none
| Error e -> model, Cmd.none
我们可以使用 Recharts 库的 Fable 绑定来绘制我们的数据集。下面的代码展示了我们如何转换和修剪数据集(在浏览器中渲染所有数据点会非常费力),并在view
函数中将它们显示为折线图。
type ChartDataPoint =
{ Date : string
Usd : float
Gbp : float
Euro : float }
let toChartData (dataSet : DataSet) =
dataSet.data
|> List.map (fun (dt, usd, gbp, eur) ->
{ Date = dt; Usd = usd; Gbp = gbp; Euro = eur } )
|> Array.ofList
|> Array.take 1000
|> Array.rev
let priceChart (chartData : ChartDataPoint[]) =
lineChart
[ Chart.Data chartData
Chart.Width 600.
Chart.Height 500. ] [
xaxis [ Cartesian.DataKey "Date" ] []
yaxis [] []
tooltip [] []
legend [] []
line [ Cartesian.Type "monotone"; Cartesian.DataKey "Gbp" ] []
line [ Cartesian.Type "monotone"; Cartesian.DataKey "Euro" ] []
line [ Cartesian.Type "monotone"; Cartesian.DataKey "Usd" ] []
]
let view (model : SilverAndGold option ) dispatch =
div [ ] [
match model with
| Some sets ->
yield h2 [] [ str "Silver" ]
yield priceChart (toChartData sets.Silver)
yield h2 [] [ str "Gold" ]
yield priceChart (toChartData sets.Gold)
| None ->
yield h2 [] [ str "No data :("]
]
我制作了一个非常小的Elmish应用程序,其中包含所有这些主题。您可以在此处找到它,并根据您的需要进行调整。