失败时中断进程
Break process in case of fail
我正在 elixir 中开发一个 API,我有一个进程连续执行 6 个动作。我的问题是,如果这 6 个操作中的任何一个失败,我该如何中断此执行?
我不想级联成多个案例块。
实际上我想要“return”之类的东西。
有人对此有好的解决方案吗?
当你在 Elixir 中有一系列连续的条件语句(例如多个 case 块)时,with
子句(语句?运算符?)会很有用。
Elixir docs中有一个例子。
比较像这样的一团乱七八糟的嵌套 case 语句:
case op1(x) do
{:ok, result1} ->
case op2(result1) do
{:ok, result2} ->
case op3(result2) do
{:ok, result3} -> {:ok, result3}
{:error, error} -> {:error, error}
end
{:error, error} -> {:error, error}
end
{:error, error} -> {:error, error}
end
那 真的 很难理解,而且 {:error, error} -> {:error, error}
位感觉多余。基本上,我们只想继续钻取顺序操作(1、2、3、...)或退出并出错。
我们可以使用 with
语法重写上面的内容——注意箭头的方向!
with {:ok, result1} <- op1(x),
{:ok, result2} <- op2(result1) do
op3(result3)
else
{:error, error} -> {:error, error}
end
或更简洁地说,如果不需要特殊的错误处理,则省略 else
块:
with {:ok, result1} <- op1(x),
{:ok, result2} <- op2(result1) do
op3(result3)
end
您可以使用逗号分隔一个又一个操作,最后在一个 do
块中结束,您可以在其中执行最后一个操作。
如果任何操作失败,可以将执行路由到可选的 else
块中向下匹配——如果您需要区分不同的 return 值(例如,如果需要特定的日志记录),否则 else
块是多余的,通常可以省略。
理解 with
块是编写更清晰的 Elixir 代码的一大步。使用 with
语法的替代方法是编写多个函数签名来处理每个步骤的输出,但这感觉像是很多并不总是合理的繁忙工作。
没有 return 选项真的让我在 elixir 中困扰了一段时间。我建议你拥抱模式匹配。我知道这似乎不正确,但您最终会意识到其背后的简单性。你可以不用嵌套,只需要为你期望的每个模式创建一个新函数即可。
这是我基本上递归 self()
的片段
...
def handle_cast({:get_name, port, container}, state) do
app_name = Map.get(container, "Labels") |> Map.get("app")
GenServer.cast(self(), {:domain_map, app_name, port, container})
{:noreply, state}
end
def handle_cast({:containers, containers}, state) do
Enum.map(containers, fn container ->
GenServer.cast(self(), {:container, container})
end)
{:noreply, state}
end
def handle_cast({:container, container}, state) do
Enum.map(Map.get(container, "Ports"), fn port ->
GenServer.cast(self(), {:get_name, port, container})
end)
{:noreply, state}
end
...
如果模式不匹配,那基本上就是您的 return 语句。
我正在 elixir 中开发一个 API,我有一个进程连续执行 6 个动作。我的问题是,如果这 6 个操作中的任何一个失败,我该如何中断此执行?
我不想级联成多个案例块。
实际上我想要“return”之类的东西。
有人对此有好的解决方案吗?
当你在 Elixir 中有一系列连续的条件语句(例如多个 case 块)时,with
子句(语句?运算符?)会很有用。
Elixir docs中有一个例子。
比较像这样的一团乱七八糟的嵌套 case 语句:
case op1(x) do
{:ok, result1} ->
case op2(result1) do
{:ok, result2} ->
case op3(result2) do
{:ok, result3} -> {:ok, result3}
{:error, error} -> {:error, error}
end
{:error, error} -> {:error, error}
end
{:error, error} -> {:error, error}
end
那 真的 很难理解,而且 {:error, error} -> {:error, error}
位感觉多余。基本上,我们只想继续钻取顺序操作(1、2、3、...)或退出并出错。
我们可以使用 with
语法重写上面的内容——注意箭头的方向!
with {:ok, result1} <- op1(x),
{:ok, result2} <- op2(result1) do
op3(result3)
else
{:error, error} -> {:error, error}
end
或更简洁地说,如果不需要特殊的错误处理,则省略 else
块:
with {:ok, result1} <- op1(x),
{:ok, result2} <- op2(result1) do
op3(result3)
end
您可以使用逗号分隔一个又一个操作,最后在一个 do
块中结束,您可以在其中执行最后一个操作。
如果任何操作失败,可以将执行路由到可选的 else
块中向下匹配——如果您需要区分不同的 return 值(例如,如果需要特定的日志记录),否则 else
块是多余的,通常可以省略。
理解 with
块是编写更清晰的 Elixir 代码的一大步。使用 with
语法的替代方法是编写多个函数签名来处理每个步骤的输出,但这感觉像是很多并不总是合理的繁忙工作。
没有 return 选项真的让我在 elixir 中困扰了一段时间。我建议你拥抱模式匹配。我知道这似乎不正确,但您最终会意识到其背后的简单性。你可以不用嵌套,只需要为你期望的每个模式创建一个新函数即可。
这是我基本上递归 self()
...
def handle_cast({:get_name, port, container}, state) do
app_name = Map.get(container, "Labels") |> Map.get("app")
GenServer.cast(self(), {:domain_map, app_name, port, container})
{:noreply, state}
end
def handle_cast({:containers, containers}, state) do
Enum.map(containers, fn container ->
GenServer.cast(self(), {:container, container})
end)
{:noreply, state}
end
def handle_cast({:container, container}, state) do
Enum.map(Map.get(container, "Ports"), fn port ->
GenServer.cast(self(), {:get_name, port, container})
end)
{:noreply, state}
end
...
如果模式不匹配,那基本上就是您的 return 语句。