Return 来自 Fable.Remoting 的异步值
Return async value from Fable.Remoting
这是客户端 Fable.Remoting 打印异步函数结果的示例。
// Client code (Compiled to Javascript using Fable)
// ============
open Fable.Remoting.Client
let server = Proxy.create<IServer>
async {
let! length = server.getLength “hello”
do printfn “%d” length // 5
}
|> Async.StartImmediate
如何获取 length
值?
Async 是您在 F# 中使用 return
的地方之一。所以你需要return这个长度值。还有,Async.StartImmediate
returns()
(单位)。使用其他东西,例如Async.RunSynchronously
如果您需要提取的值。取决于你需要用它实现什么。
let length =
async {
let! length = async {return String.length "hello"}
do printfn "%d" length // 5
return length
} |> Async.RunSynchronously
length // val it : int = 5
顺便说一句,你提到了寓言。所以你也许可以使用 JS promise
.
F# 中有关 Async 的一些资源:
我看到你用 elmish, so I'm going to assume you have a Msg
type defined. Don't use Async.StartImmediate
or Async.RunSynchronously
; in Elmish, you should use Cmd.OfAsync
标记了你的问题,以安排在异步块 returns 一个值后发送一条消息。 Cmd.OfAsync
中有四个函数(同样的四个也出现在 Cmd.OfPromise
中):either
、perform
、attempt
和 result
.我会为您分解它们,因为它们的文档还不够完善:
either
:接受四个参数,task
、arg
、ofSuccess
和ofError
。 task
是您要调用的异步函数('a -> Async<'b>
类型)。 arg
是要传递给 task
函数的 'a
类型的参数。 ofSuccess
是类型 'b -> 'Msg
的函数:它将接收异步函数的结果,并应该创建一条消息,大概是包含 'b
结果的消息。最后,ofError
是一个类型为 exn -> 'Msg
的函数:如果 task
函数抛出异常,那么 ofError
将被调用而不是 ofSuccess
,并且假设将该异常转换为您的代码可以处理的 Elmish 消息(大概是将错误记录到 Javascript 控制台或弹出带有 Thoth.Toast 或类似内容的通知)。
perform
:类似either
,但没有ofError
参数。如果您的异步命令不会失败(远程 API 调用永远不会出现这种情况,因为它总是有可能网络中断或您的服务器无响应),或者如果您只是不关心异常并且不介意抛出未处理的异常。
attempt
:和either
一样,但是没有ofSuccess
参数,所以task
函数的结果如果成功就会被忽略。
result
:这个完全不一样。它只需要一个 Async<'Msg>
类型的参数,即您将一个 async
块传递给它,该块已经将生成一条消息。
使用您编写的代码,如果您想对代码进行最少的更改,您可以使用 Cmd.OfAsync.result
,但我建议改用 Cmd.OfAsync.perform
(并将其升级为 Cmd.OfAsync.either
一旦你写了一些错误处理代码)。我会告诉你两种方式:
type Msg =
// ... rest of your messages go here
| GetLength of string
| LengthResult of int
let update msg model =
match msg with
// ... rest of your update function
| GetLength s ->
let usePerform = true
if usePerform then
model, Cmd.OfAsync.perform server.getLength s LengthResult
else
let length : Async<Msg> = async {
let! length = server.getLength s
return (LengthResult length)
}
model, Cmd.OfAsync.result length
| LengthResult len ->
// Do whatever you needed to do with the API result
printfn "Length was %d" len
model, Cmd.none
如果您使用 either
(一旦投入生产,您确实应该这样做),将会有第三条消息 LogError of exn
,其处理方式如下:
| LogError e ->
printfn "Error: %s" e.Message
model, Cmd.none
并且上面代码中的 Cmd.OfAsync.perform
行将变为:
model, Cmd.OfAsync.either server.getLength s LengthResult LogError
这是在 Elmish 中处理异步生成函数的正确方法。
对于那些想从 js 代码调用的人。
// Client code (Compiled to Javascript using Fable)
// ============
open Fable.Remoting.Client
open Fable.Core // required for Async.StartAsPromise
let server = Proxy.create<IServer>
let len_from_fable () =
async {
let! length = server.getLength “hello”
return length
} |> Async.StartAsPromise
从 js 调用
async func() {
let len = await len_from_fable()
print(len)
}
适用于寓言 3.0。
这是客户端 Fable.Remoting 打印异步函数结果的示例。
// Client code (Compiled to Javascript using Fable)
// ============
open Fable.Remoting.Client
let server = Proxy.create<IServer>
async {
let! length = server.getLength “hello”
do printfn “%d” length // 5
}
|> Async.StartImmediate
如何获取 length
值?
Async 是您在 F# 中使用 return
的地方之一。所以你需要return这个长度值。还有,Async.StartImmediate
returns()
(单位)。使用其他东西,例如Async.RunSynchronously
如果您需要提取的值。取决于你需要用它实现什么。
let length =
async {
let! length = async {return String.length "hello"}
do printfn "%d" length // 5
return length
} |> Async.RunSynchronously
length // val it : int = 5
顺便说一句,你提到了寓言。所以你也许可以使用 JS promise
.
F# 中有关 Async 的一些资源:
我看到你用 elmish, so I'm going to assume you have a Msg
type defined. Don't use Async.StartImmediate
or Async.RunSynchronously
; in Elmish, you should use Cmd.OfAsync
标记了你的问题,以安排在异步块 returns 一个值后发送一条消息。 Cmd.OfAsync
中有四个函数(同样的四个也出现在 Cmd.OfPromise
中):either
、perform
、attempt
和 result
.我会为您分解它们,因为它们的文档还不够完善:
either
:接受四个参数,task
、arg
、ofSuccess
和ofError
。task
是您要调用的异步函数('a -> Async<'b>
类型)。arg
是要传递给task
函数的'a
类型的参数。ofSuccess
是类型'b -> 'Msg
的函数:它将接收异步函数的结果,并应该创建一条消息,大概是包含'b
结果的消息。最后,ofError
是一个类型为exn -> 'Msg
的函数:如果task
函数抛出异常,那么ofError
将被调用而不是ofSuccess
,并且假设将该异常转换为您的代码可以处理的 Elmish 消息(大概是将错误记录到 Javascript 控制台或弹出带有 Thoth.Toast 或类似内容的通知)。perform
:类似either
,但没有ofError
参数。如果您的异步命令不会失败(远程 API 调用永远不会出现这种情况,因为它总是有可能网络中断或您的服务器无响应),或者如果您只是不关心异常并且不介意抛出未处理的异常。attempt
:和either
一样,但是没有ofSuccess
参数,所以task
函数的结果如果成功就会被忽略。result
:这个完全不一样。它只需要一个Async<'Msg>
类型的参数,即您将一个async
块传递给它,该块已经将生成一条消息。
使用您编写的代码,如果您想对代码进行最少的更改,您可以使用 Cmd.OfAsync.result
,但我建议改用 Cmd.OfAsync.perform
(并将其升级为 Cmd.OfAsync.either
一旦你写了一些错误处理代码)。我会告诉你两种方式:
type Msg =
// ... rest of your messages go here
| GetLength of string
| LengthResult of int
let update msg model =
match msg with
// ... rest of your update function
| GetLength s ->
let usePerform = true
if usePerform then
model, Cmd.OfAsync.perform server.getLength s LengthResult
else
let length : Async<Msg> = async {
let! length = server.getLength s
return (LengthResult length)
}
model, Cmd.OfAsync.result length
| LengthResult len ->
// Do whatever you needed to do with the API result
printfn "Length was %d" len
model, Cmd.none
如果您使用 either
(一旦投入生产,您确实应该这样做),将会有第三条消息 LogError of exn
,其处理方式如下:
| LogError e ->
printfn "Error: %s" e.Message
model, Cmd.none
并且上面代码中的 Cmd.OfAsync.perform
行将变为:
model, Cmd.OfAsync.either server.getLength s LengthResult LogError
这是在 Elmish 中处理异步生成函数的正确方法。
对于那些想从 js 代码调用的人。
// Client code (Compiled to Javascript using Fable)
// ============
open Fable.Remoting.Client
open Fable.Core // required for Async.StartAsPromise
let server = Proxy.create<IServer>
let len_from_fable () =
async {
let! length = server.getLength “hello”
return length
} |> Async.StartAsPromise
从 js 调用
async func() {
let len = await len_from_fable()
print(len)
}
适用于寓言 3.0。