【问题标题】:How do I handle custom errors, globally, in Phoenix?如何在 Phoenix 中全局处理自定义错误?
【发布时间】:2016-04-27 15:22:10
【问题描述】:

我在我的应用程序中使用了一个库,它定期返回 {:ok, value}{:error, error} 的元组。在我们假设可能存在错误(例如用户输入)的情况下,我们会明确处理这些情况。对于所有其他情况,我更愿意假设它们将得到妥善处理,如果没有,则通过重定向处理失败情况。

我开始尝试使用一个函数来解决这个问题:

def show(conn, %{"id" => id}) do
  user = client.user_show(conn.assigns.endpoint, id) |> get_value(conn)
  # rest of method omitted
end

def get_value({:ok, value}, _conn), do: value

def get_value({:error, value}, conn)  do
  conn
  |> put_flash(:error, "Client error")
  |> redirect(to: "/")
  |> halt
end

这似乎是个好主意,但不幸的是,尽管停止了,但 conn 仍在继续。这是有道理的,因为代码路径没有拆分。

因此,似乎更好的解决方案是实现此函数以引发特定错误,然后尝试全局解决它。

很遗憾,我找不到在 Phoenix 的全局级别上处理错误的方法。我看到的唯一可能的选项是使用ErrorView,但我不想仅仅显示错误,我想根据错误进行适当的重定向。

我是否遗漏了什么或者这在凤凰城目前是不可能的?

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    halt 函数实际上并不提供任何分支逻辑。它只将conns 私有字段halted 设置为true。这可确保其他 plugs 不会进一步处理它,但其余操作将处理它并覆盖 halted 字段。

    解决方案是将此功能移到插件中。

    def client_error_plug(conn) do
      user = client.user_show(conn.assigns.endpoint, id) |> get_value(conn)
      case user do
        {:ok, user} ->
          assign(conn, :current_user, user)
        {:error, reason} -> 
          conn
          |> put_flash(:error, "Client error")
          |> redirect(to: "/")
          |> halt
      end
    end
    

    然后在你的控制器中放"

    plug :client_error_plug when action in [:show, ...]
    

    给这个插件起一个更有意义的名字可能是有意义的,但这取决于应用程序逻辑:) 现在你可以确定你有用户在分配,因为如果它不在那里,重定向就会启动。

    【讨论】:

      猜你喜欢
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-28
      • 1970-01-01
      • 2018-08-07
      相关资源
      最近更新 更多