Papillon6814
What's the best way of handling error?
Hello.
I’m a beginner programmer from Japan.
I’m in trouble of handling error…
auth_controller.ex
def signup(conn, params) do
url = @db_domain_url <> @api_url <> @signup_url
try do
attrs = Poison.encode!(params)
rescue
_ ->
render("error.json", "Failed to encode json from client", 2000)
end
try do
{:ok, response} = HTTPoison.post(url, attrs, @content_type)
rescue
_ ->
render("error.json", "POST Request failed", 3000)
end
try do
body = Poison.decode!(response.body)
rescue
_ ->
render("error.json", "Failed to decode json from DB server", 2001)
end
render("show.json", body)
end
auth_view.ex
defmodule PappapWeb.AuthView do
use PappapWeb, :view
def render("show.json", %{} = body) do
body
end
def render("error.json", msg, error_no) do
%{
"result" => false,
"reason" => msg,
"error_no" => error_no
}
end
end
Those are codes in my Request-Handling server. It receives requests from ios, and then it fetches data from Database server.
To prevent crash of ios, I want to handle error in good ways. But I don’t know how to do that. With those codes, my server did not start due to an error.
== Compilation error in file lib/pappap_web/controllers/auth_controller.ex ==
** (CompileError) lib/pappap_web/controllers/auth_controller.ex:20: undefined function attrs/0
(elixir 1.10.3) src/elixir_locals.erl:114: anonymous fn/3 in :elixir_locals.ensure_no_undefined_local/3
(stdlib 3.13) erl_eval.erl:680: :erl_eval.do_apply/6
(elixir 1.10.3) lib/kernel/parallel_compiler.ex:304: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
I know it is a problem of variable scopes… but I’m not sure what is the best way to handle errors…
Help me!
Most Liked
hauleth
with {:req, {:ok, attrs}} <- {:req, Poison.encode(params)},
{:http, {:ok, response}} <- {:http, HTTPoison.post(url, attrs, @content_type)},
{:resp, {:ok, body}} <- {:resp, Poison.decode(response.body)}
do
render("show.json", body)
else
{:req, _} -> render("error.json", "Failed to encode json from client", 2000)
{:http, _} -> render("error.json", "POST Request failed", 3000)
{:resp, _} -> render("error.json", "Failed to decode json from DB server", 2001)
end
Alternatively you can use action_fallback/1 for handling errors:
# Handler
with {:req, {:ok, attrs}} <- {:req, Poison.encode(params)},
{:http, {:ok, response}} <- {:http, HTTPoison.post(url, attrs, @content_type)},
{:resp, {:ok, body}} <- {:resp, Poison.decode(response.body)}
do
render("show.json", body)
end
# Action fallback
def call(conn, {:req, _}), do: render("error.json", "Failed to encode json from client", 2000)
def call(conn, {:http, _}), do: render("error.json", "POST Request failed", 3000)
def call(conn, {:resp, _}), do: render("error.json", "Failed to decode json from DB server", 2001)
hauleth
Because exceptions are mean to be used in exceptional cases, not when you need flow control. All of the cases mentioned above are expected cases, not exceptions.
kokolegorille
It is not a common pattern to use try and catch clause… and Yes, it’s a scoping problem.
But before solving the scope, You might want to refactor a little bit.
If You think something can go wrong, You could use the “soft” Poison.encode, instead of Poison.encode!, which raise an error.
You just have to deal with {:ok, result}, or {:error, reason}.
And because You have multiple conditions, I would be tempted to use with.
with {:ok, attrs} <- Poison.encode(params),
{:ok, response} <- HTTPoison.post(url, attrs, @content_type),
{:ok, body} <- Poison.decode(response.body) do
render("show.json", body)
else
... # Manage errors here!
end
I would always try to avoid try and catch
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









