如何处理 Elixir 中的尝试和救援错误

How to handle try and rescue errors in Elixir

我正在使用 try and rescue,但它不起作用。当我这样做时,

iex(3)> try do
...(3)>   File.read! "junaid"
...(3)> rescue
...(3)>   error ->
...(3)>     IO.inspect error
...(3)> end
%File.Error{action: "read file", path: "junaid", reason: :enoent}
%File.Error{action: "read file", path: "junaid", reason: :enoent}

但是当我用我自己的方法使用它时,比如

iex(2)> try do                                                     
...(2)>   EvercamMedia.S3.do_save_multiple(%{"junaid" => "junaid"})
...(2)> rescue                                                     
...(2)>    error ->                                                
...(2)>      IO.inspect error                                      
...(2)> end

但它不会工作并给我这样的错误

[error] Task #PID<0.1075.0> started from #PID<0.1065.0> terminating
** (File.Error) could not read file "junaid": no such file or directory
    (elixir 1.11.1) lib/file.ex:354: File.read!/1
    (evercam_media 1.0.1607441172) lib/evercam_media/s3.ex:46: anonymous fn/1 in EvercamMedia.S3.do_save_multiple/1

是否可以绕过此错误并 do_something() 进行救援?或者在任何其他条款中说,这是一个错误?而不是中断进程?

为什么 try 和 rescue 不能以这样的方式工作,它会在 try 中完成工作,如果有任何错误,它只会去救援而不中断进程。

更新:方法,EvercamMedia.S3.do_save_multiple

  def do_save_multiple(paths) do
    upload_file = fn {src_path, dest_path} ->
      ExAws.S3.put_object("evercam-camera-assets", dest_path, File.read!(src_path),
        acl: :public_read
      )
      |> ExAws.request!()
    end

    paths
    |> Task.async_stream(upload_file, max_concurrency: 10, timeout: :infinity)
    |> Stream.run()
  end

试图挽救这里的错误存在一个根本问题:EvercamMedia.S3.do_save_multiple/1 似乎 产生了一个任务 ,这意味着代码不会引发任何错误 within this process,这使得试图在这个进程中处理它变得毫无意义。这就像试图在巴塞罗那机场赶上从巴黎飞往维也纳的航班。

如果您拥有 EvercamMedia.S3.do_save_multiple/1,请修复那里的错误。如果你不这样做,你可能 trap exits in the calling process and perform whatever you want in handle_info({:EXIT, _, _}, state) callback, or simply spawn it unlinked via e. g. Kernel.spawn/1

spawn(fn ->
  EvercamMedia.S3.do_save_multiple(%{"junaid" => "junaid"})
end)