Hi, I’d like to know about the following things. Please give me feedback.
- Is using Task for HTTP requests a bad practice? If so, why?
- How do people use HTTP requests in real projects?
A bit too long, sorry!
Context
elm/http 2.0.0 came out recently, which is great for anyone who want file upload and simple requests. However, I found that using Task with the new API is quite difficult comparing with the 1.x API. Yes, it is very simple when we use Cmd, but when switching to Task for some reason, we should spend a high cost.
The doc comment on Http.task
says:
Just like request, but it creates a Task. This makes it possible to pair your HTTP request with Time.now if you need timestamps for some reason. This should be quite rare.
Why? No reason is written there. Now I’m in an uncomfortable state, because I use Task Http.Error Something
everywhere in a project at work but it looks like Task API is going to be deprecated or finally removed in the future. I don’t know, but at least Evan thinks tasks should be quite rare.
I remember the old elm-spa-example was also using Task.map2
for initializing some pages, but everything was completely reachitected and now uses Cmd.batch
instead. package.elm-lang.com also uses Cmd.batch
.
So I want to know using Tasks is a bad practice or not.
Our Project
In our project, most APIs are designed to be RESTful. One resource at one endpoint. So we often need to get multiple data at once to initialize the pages. Using Task.map2
and Task.map3
to gather the data, Task.andThen
to get the related data and Task.onError
to fallback or retry. So every request function is Task based.
I know functions like Task.map3
are not parallel. But Cmd.batch
requires more complex code than Task.map*
. It requires 3 Maybe
(or Result
, etc.) fields in Model
, 3 branches in Msg
and a bit more complex pattern matching in view
function.
Yes, it has some benefit. Every request can be tracked as Msg
, rendering the partial data faster even if some other part fails, etc. But …honestly, these are not the first thing for us.
One day I faced a problem where an API is unstable and sometimes failed for some reasons. Then I quickly modified a function to retry at most 10 times, without breaking anything. The reviewer had never learned Elm but quickly understand how I fixed the behavior. It was a very nice experience!
Of course, I could use Cmd to show “retrying 6…7…” to users but it was not what I needed at that time. If I needed this, I can switch to Cmd gradually. From Task to Cmd is easy, the opposite is not.
How about the other Projects?
I think Task works well in our project, but is it particular to our case? How about the majority of front-end projects?
I talked about this with @lucamug He was comfortable to use Cmd and doesn’t need Task at all. In their project, server and front is developed together, so no such complex request in frontend code.
I agree that this is a good way to reduce the number of requests. Chatty API (which often requires N+1 requests) is a bad pattern. I know, but real project is not always ideal!
I’m very interested in how other projects is doing with HTTP requests. I have not experienced so many SPA projects. If you know something, please share it here! (Also welcome if you are not doing a typical web development)
Is Cmd working well for your project? When do you use Task? I just want to know how things should be, and hopefully make Task requests live longer.
Thanks!
Experiment
If you are interested, I built an experimental library to solve my own problem. (Warning: still very WIP yet!) It is basically Task based, and
steal the ideahighly inspired by elm-http-builder.It extremely cares about the ability of gradual switching. How to switch simple
get
to more complex request? How to switch from Task to Cmd? How to switchHttp.Error
toReq.Error
with more information? How quickly implement features when niche information get suddenly needed? etc.