在 FFI 中使用 Aff 回调函数
Function with Aff callback in FFI
我正在尝试包装一个 Javascript 库,其中我有一个方法 A.bar(f)
,它将一个函数 f : B -> void
.
作为参数
因为我想使用 bar
来执行一些异步计算,在 Purescript 方面,我有一个函数声明
foreign import foo :: Fn2 A (B -> Aff Unit) -> EffectFnAff Unit
在其相应的 Javascript 文件中,我有类似
的内容
exports.foo = function (a, f) {
return function (onError, onSuccess) {
a.bar(function (b) {
f(b)
})
return function (cancelError, cancelerError, cancelerSuccess) {
cancelerSuccess()
}
}
}
我遇到的问题是 f(b)
是一个 Aff
对象,我不知道如何在 Javascript 端执行它。
从 FFI-ied JavaScript 访问 PureScript 数据结构总是一个坏主意。您不仅依赖于编写库的特定方式(没有编译器支持来捕获错误!),而且还依赖于编译器本身,因为运行时表示可能会从一个编译器版本更改为另一个编译器版本(请注意,这不会适用于 EffectFnAff
,因为它明确适用于 FFI 并经过仔细定义,in terms of EffectFn2
)。
在 FFI 中表示有效计算的方法是通过 Effect
:
foreign import foo :: Fn2 A (B -> Effect Unit) -> EffectFnAff Unit
这样的函数现在可以从 JavaScript 中以您的方式调用 - 如 f(b)
.
如果您希望图书馆的消费者提供 Aff
,您要做的就是制作一个包装器:
foreign import foo_ :: Fn2 A (B -> Effect Unit) (EffectFnAff Unit)
foo :: A -> (B -> Aff Unit) -> Aff Unit
foo a f = fromEffectFnAff $ runFn2 foo_ a (launchAff_ <<< f)
那么您只需导出包装器 foo
,而不是 FFI 导入 foo_
。
在某种程度上相关的说明中,我还建议取消 EffectFnAff
,因为您实际上并没有启动任何异步操作,而是始终调用 cancelerSuccess()
.
因此,我会推荐这个:
// JavaScript
exports.foo = (a, f) => a.bar(f)
-- PureScript
foreign import foo_ :: EffectFn2 A (B -> Effect Unit) Unit
foo :: A -> (B -> Aff Unit) -> Aff Unit
foo a f = liftEffect $ runEffectFn2 foo_ a (launchAff_ <<< f)
包装器在两个地方仍然有 Aff
- 这是假设您出于自己的原因需要将整个东西放入 Aff
。否则它可能只是 foo = runEffectFn2 foo_
我正在尝试包装一个 Javascript 库,其中我有一个方法 A.bar(f)
,它将一个函数 f : B -> void
.
因为我想使用 bar
来执行一些异步计算,在 Purescript 方面,我有一个函数声明
foreign import foo :: Fn2 A (B -> Aff Unit) -> EffectFnAff Unit
在其相应的 Javascript 文件中,我有类似
的内容exports.foo = function (a, f) {
return function (onError, onSuccess) {
a.bar(function (b) {
f(b)
})
return function (cancelError, cancelerError, cancelerSuccess) {
cancelerSuccess()
}
}
}
我遇到的问题是 f(b)
是一个 Aff
对象,我不知道如何在 Javascript 端执行它。
从 FFI-ied JavaScript 访问 PureScript 数据结构总是一个坏主意。您不仅依赖于编写库的特定方式(没有编译器支持来捕获错误!),而且还依赖于编译器本身,因为运行时表示可能会从一个编译器版本更改为另一个编译器版本(请注意,这不会适用于 EffectFnAff
,因为它明确适用于 FFI 并经过仔细定义,in terms of EffectFn2
)。
在 FFI 中表示有效计算的方法是通过 Effect
:
foreign import foo :: Fn2 A (B -> Effect Unit) -> EffectFnAff Unit
这样的函数现在可以从 JavaScript 中以您的方式调用 - 如 f(b)
.
如果您希望图书馆的消费者提供 Aff
,您要做的就是制作一个包装器:
foreign import foo_ :: Fn2 A (B -> Effect Unit) (EffectFnAff Unit)
foo :: A -> (B -> Aff Unit) -> Aff Unit
foo a f = fromEffectFnAff $ runFn2 foo_ a (launchAff_ <<< f)
那么您只需导出包装器 foo
,而不是 FFI 导入 foo_
。
在某种程度上相关的说明中,我还建议取消 EffectFnAff
,因为您实际上并没有启动任何异步操作,而是始终调用 cancelerSuccess()
.
因此,我会推荐这个:
// JavaScript
exports.foo = (a, f) => a.bar(f)
-- PureScript
foreign import foo_ :: EffectFn2 A (B -> Effect Unit) Unit
foo :: A -> (B -> Aff Unit) -> Aff Unit
foo a f = liftEffect $ runEffectFn2 foo_ a (launchAff_ <<< f)
包装器在两个地方仍然有 Aff
- 这是假设您出于自己的原因需要将整个东西放入 Aff
。否则它可能只是 foo = runEffectFn2 foo_