作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在elixir GenServer
中,有sync和async方法,handle_cast
和handle_call
。在异步情况下,如果该方法失败,我如何获得通知?
方法失败意味着在handle_call
方法中,我需要定义一些逻辑来查询/写入数据库。如果数据库操作失败,我需要将此失败通知调用者。在异步方法中,我该怎么做?
最佳答案
因此,鼓励您“让它死去”的评论通常是正确的。惯用的 Erlang 和 Elixir 呼吁“快速失败”,并让主管重启任何崩溃的组件。
也就是说,有时崩溃是不合适的;通常是在您知道可能会出现负面结果时。标准库中的许多 API 通过返回结果元组来处理此问题,即 {:ok, result}
或 {:error, reason}
并使其由调用代码负责崩溃或尝试其他方法。
在您的用例中,我认为您应该只使用数据调用进程中的数据库写入/查询代码,根本不使用异步方法,首先修复数据库性能。如果这确实是一个长时间运行的查询,并且优化数据库不是正确的答案,那么您的下一个最佳选择是 Task
模块(documentation here),它是 Elixir 标准库的一部分 - 它提供用于异步任务执行的内置功能。</p>
我知道人们不回答您的问题是多么令人沮丧,所以我会回答;但请注意,这几乎肯定不是解决原始问题的正确方法。
关键是将调用进程的 pid 传递给 Worker,以便它可以稍后发送结果消息:
defmodule CastBackExampleWorker do
use GenServer
# ...
def do_operation(args) do
caller = self()
ref = make_ref()
# Pass the caller's pid to the GenServer so that it can message back later
GenServer.cast(__MODULE__, {:do_operation, caller, ref, args})
# hand back a unique ref for this request
ref
end
# ...
def handle_cast({:do_operation, caller, ref, args}, state) do
case execute_operation(args) do
{:ok, result} -> send(caller, {__MODULE__, ref, {:ok, result}})
{:error, reason} -> send(caller, {__MODULE__, ref, {:error, reason}})
end
{:noreply, state}
end
end
defmodule CastBackExampleClient do
use GenServer
# ...
def handle_call(:my_real_work, _from, state) do
# ignoring the ref, but we could stick it into our state for later...
_ref = CastBackExampleWorker.do_operation([])
{:reply, :ok, state}
end
def handle_info({CastBackExampleWorker, _ref, outcome}, state) do
# Do something with the outcome here
{:noreply, state}
end
end
关于elixir - 如何在 GenServer 中获得有关异步失败的通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48727296/
我是一名优秀的程序员,十分优秀!