{"action":"created","comment":{"url":"https://api.github.com/repos/allo-media/tech-blog/pulls/comments/166690038","pull_request_review_id":94794109,"id":166690038,"diff_hunk":"@@ -0,0 +1,342 @@\n+---\n+layout: post\n+title:  \"Chaining HTTP requests in Elm\"\n+excerpt: \"Sometimes in Elm you struggle with the most basic things. Especially when you come from a JavaScript background, where chaining HTTP requests are relatively easy thanks to Promises or async/await.\"\n+date:   2018-02-05 09:00:00 +0100\n+categories: learning elm\n+tags: elm http\n+---\n+\n+Sometimes in Elm you struggle with the most basic things.\n+\n+Especially when you come from a JavaScript background, where chaining HTTP requests are relatively easy thanks to Promises. Here's a real-world example leveraging the Github public API, where we fetch a list of Github events, pick the first one and query some user information from its unique identifier.\n+\n+The first request uses the `https://api.github.com/events` endpoint, and the JSON retrieved looks like this:\n+\n+```json\n+[\n+    {\n+        \"id\": \"987654321\",\n+        \"type\": \"ForkEvent\",\n+        \"actor\": {\n+            \"id\": 1234567,\n+            \"login\": \"foobar\",\n+        }\n+    },\n+]\n+```\n+\n+I'm purposely omitting a lot of other properties from the records here, for brevity.\n+\n+The second request we need to do is on the `https://api.github.com/users/{login}` endpoint, and its body looks like this:\n+\n+```json\n+{\n+    \"id\": 1234567,\n+    \"login\": \"foobar\",\n+    \"name\": \"Foo Bar\",\n+}\n+```\n+\n+Again, I'm just displaying a few fields from the actual JSON body here.\n+\n+So we basically want:\n+\n+- from a list of events, to pick the first one if any,\n+- then pick its `actor.login` property,\n+- query the user details endpoint using this value,\n+- extract the user real name for that account.\n+\n+Using JavaScript, that would look like this:\n+\n+```js\n+fetch(\"https://api.github.com/events\")\n+    .then(responseA => {\n+        return responseA.json()\n+    })\n+    .then(events => {\n+        if (events.length == 0) {\n+            throw \"No events.\"\n+        }\n+        const { actor : { login } } = events[0]\n+        return fetch(`https://api.github.com/users/${login}`)\n+    })\n+    .then(responseB => {\n+        return responseB.json()\n+    })\n+    .then(user => {\n+        if (!user.name) {\n+            console.log(\"unspecified\")\n+        } else {\n+            console.log(user.name)\n+        }\n+    })\n+    .catch(err => {\n+        console.error(err)\n+    })\n+```\n+\n+It would get a little fancier using `async/await`:\n+\n+```js\n+try {\n+    const responseA = await fetch(\"https://api.github.com/events\")\n+    const events = await responseA.json()\n+    if (events.length == 0) {\n+        throw \"No events.\"\n+    }\n+    const { actor: { login } } = events[0]\n+    const responseB = await fetch(`https://api.github.com/users/${login}`)\n+    const user = await responseB.json()\n+    if (!user.name) {\n+        console.log(\"unspecified\")\n+    } else {\n+        console.log(user.name)\n+    }\n+} catch (err) {\n+    console.error(err)\n+}\n+```\n+\n+This is already complicated code to read and understand, and it's tricky to do using Elm as well. Let's see how to achieve the same understanding exactly what we're doing (we've all blindly copied and pasted code in the past, don't deny).\n+\n+First, let's write the two requests we need; one for fetching the list of events, the second to obtain a given user's details from her `login`:\n+\n+```haskell\n+import Http\n+import Json.Decode as Decode\n+\n+eventsRequest : Http.Request (List String)\n+eventsRequest =\n+    Http.get \"https://api.github.com/events\"\n+        (Decode.at [ \"actor\", \"login\" ] Decode.string\n+            |> Decode.list","path":"_posts/2018-02-05-chaining-http-requests-in-elm.md","position":113,"original_position":113,"commit_id":"babf6457aef8b6227eb92c4c1aac8ce7e87aae7f","original_commit_id":"babf6457aef8b6227eb92c4c1aac8ce7e87aae7f","user":{"login":"vjousse","id":154904,"avatar_url":"https://avatars3.githubusercontent.com/u/154904?v=4","gravatar_id":"","url":"https://api.github.com/users/vjousse","html_url":"https://github.com/vjousse","followers_url":"https://api.github.com/users/vjousse/followers","following_url":"https://api.github.com/users/vjousse/following{/other_user}","gists_url":"https://api.github.com/users/vjousse/gists{/gist_id}","starred_url":"https://api.github.com/users/vjousse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vjousse/subscriptions","organizations_url":"https://api.github.com/users/vjousse/orgs","repos_url":"https://api.github.com/users/vjousse/repos","events_url":"https://api.github.com/users/vjousse/events{/privacy}","received_events_url":"https://api.github.com/users/vjousse/received_events","type":"User","site_admin":false},"body":"Wouldn't (Decode.list <| Decode.at [ \"actor\", \"login\" ] Decode.string) work?","created_at":"2018-02-07T17:18:54Z","updated_at":"2018-02-07T17:18:54Z","html_url":"https://github.com/allo-media/tech-blog/pull/13#discussion_r166690038","pull_request_url":"https://api.github.com/repos/allo-media/tech-blog/pulls/13","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/allo-media/tech-blog/pulls/comments/166690038"},"html":{"href":"https://github.com/allo-media/tech-blog/pull/13#discussion_r166690038"},"pull_request":{"href":"https://api.github.com/repos/allo-media/tech-blog/pulls/13"}},"in_reply_to_id":166642433},"pull_request":{"url":"https://api.github.com/repos/allo-media/tech-blog/pulls/13","id":167422620,"html_url":"https://github.com/allo-media/tech-blog/pull/13","diff_url":"https://github.com/allo-media/tech-blog/pull/13.diff","patch_url":"https://github.com/allo-media/tech-blog/pull/13.patch","issue_url":"https://api.github.com/repos/allo-media/tech-blog/issues/13","number":13,"state":"open","locked":false,"title":"Chaining HTTP requests in Elm.","user":{"login":"n1k0","id":41547,"avatar_url":"https://avatars1.githubusercontent.com/u/41547?v=4","gravatar_id":"","url":"https://api.github.com/users/n1k0","html_url":"https://github.com/n1k0","followers_url":"https://api.github.com/users/n1k0/followers","following_url":"https://api.github.com/users/n1k0/following{/other_user}","gists_url":"https://api.github.com/users/n1k0/gists{/gist_id}","starred_url":"https://api.github.com/users/n1k0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/n1k0/subscriptions","organizations_url":"https://api.github.com/users/n1k0/orgs","repos_url":"https://api.github.com/users/n1k0/repos","events_url":"https://api.github.com/users/n1k0/events{/privacy}","received_events_url":"https://api.github.com/users/n1k0/received_events","type":"User","site_admin":false},"body":"This is a very early version, probably needs more polishing to become publishable. But I'd much appreciate early feedback though.","created_at":"2018-02-06T14:05:31Z","updated_at":"2018-02-07T17:18:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d28af221c04ade9a31b7a5585030788ab850d0ae","assignee":null,"assignees":[],"requested_reviewers":[{"login":"fbentz","id":2512858,"avatar_url":"https://avatars1.githubusercontent.com/u/2512858?v=4","gravatar_id":"","url":"https://api.github.com/users/fbentz","html_url":"https://github.com/fbentz","followers_url":"https://api.github.com/users/fbentz/followers","following_url":"https://api.github.com/users/fbentz/following{/other_user}","gists_url":"https://api.github.com/users/fbentz/gists{/gist_id}","starred_url":"https://api.github.com/users/fbentz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fbentz/subscriptions","organizations_url":"https://api.github.com/users/fbentz/orgs","repos_url":"https://api.github.com/users/fbentz/repos","events_url":"https://api.github.com/users/fbentz/events{/privacy}","received_events_url":"https://api.github.com/users/fbentz/received_events","type":"User","site_admin":false},{"login":"BeardedBear","id":7188702,"avatar_url":"https://avatars1.githubusercontent.com/u/7188702?v=4","gravatar_id":"","url":"https://api.github.com/users/BeardedBear","html_url":"https://github.com/BeardedBear","followers_url":"https://api.github.com/users/BeardedBear/followers","following_url":"https://api.github.com/users/BeardedBear/following{/other_user}","gists_url":"https://api.github.com/users/BeardedBear/gists{/gist_id}","starred_url":"https://api.github.com/users/BeardedBear/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BeardedBear/subscriptions","organizations_url":"https://api.github.com/users/BeardedBear/orgs","repos_url":"https://api.github.com/users/BeardedBear/repos","events_url":"https://api.github.com/users/BeardedBear/events{/privacy}","received_events_url":"https://api.github.com/users/BeardedBear/received_events","type":"User","site_admin":false},{"login":"rmonteil","id":18598001,"avatar_url":"https://avatars0.githubusercontent.com/u/18598001?v=4","gravatar_id":"","url":"https://api.github.com/users/rmonteil","html_url":"https://github.com/rmonteil","followers_url":"https://api.github.com/users/rmonteil/followers","following_url":"https://api.github.com/users/rmonteil/following{/other_user}","gists_url":"https://api.github.com/users/rmonteil/gists{/gist_id}","starred_url":"https://api.github.com/users/rmonteil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rmonteil/subscriptions","organizations_url":"https://api.github.com/users/rmonteil/orgs","repos_url":"https://api.github.com/users/rmonteil/repos","events_url":"https://api.github.com/users/rmonteil/events{/privacy}","received_events_url":"https://api.github.com/users/rmonteil/received_events","type":"User","site_admin":false}],"requested_teams":[],"milestone":null,"commits_url":"https://api.github.com/repos/allo-media/tech-blog/pulls/13/commits","review_comments_url":"https://api.github.com/repos/allo-media/tech-blog/pulls/13/comments","review_comment_url":"https://api.github.com/repos/allo-media/tech-blog/pulls/comments{/number}","comments_url":"https://api.github.com/repos/allo-media/tech-blog/issues/13/comments","statuses_url":"https://api.github.com/repos/allo-media/tech-blog/statuses/babf6457aef8b6227eb92c4c1aac8ce7e87aae7f","head":{"label":"allo-media:2018-02-05-chaining-http-request-in-elm","ref":"2018-02-05-chaining-http-request-in-elm","sha":"babf6457aef8b6227eb92c4c1aac8ce7e87aae7f","user":{"login":"allo-media","id":30897478,"avatar_url":"https://avatars0.githubusercontent.com/u/30897478?v=4","gravatar_id":"","url":"https://api.github.com/users/allo-media","html_url":"https://github.com/allo-media","followers_url":"https://api.github.com/users/allo-media/followers","following_url":"https://api.github.com/users/allo-media/following{/other_user}","gists_url":"https://api.github.com/users/allo-media/gists{/gist_id}","starred_url":"https://api.github.com/users/allo-media/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/allo-media/subscriptions","organizations_url":"https://api.github.com/users/allo-media/orgs","repos_url":"https://api.github.com/users/allo-media/repos","events_url":"https://api.github.com/users/allo-media/events{/privacy}","received_events_url":"https://api.github.com/users/allo-media/received_events","type":"Organization","site_admin":false},"repo":{"id":115030454,"name":"tech-blog","full_name":"allo-media/tech-blog","owner":{"login":"allo-media","id":30897478,"avatar_url":"https://avatars0.githubusercontent.com/u/30897478?v=4","gravatar_id":"","url":"https://api.github.com/users/allo-media","html_url":"https://github.com/allo-media","followers_url":"https://api.github.com/users/allo-media/followers","following_url":"https://api.github.com/users/allo-media/following{/other_user}","gists_url":"https://api.github.com/users/allo-media/gists{/gist_id}","starred_url":"https://api.github.com/users/allo-media/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/allo-media/subscriptions","organizations_url":"https://api.github.com/users/allo-media/orgs","repos_url":"https://api.github.com/users/allo-media/repos","events_url":"https://api.github.com/users/allo-media/events{/privacy}","received_events_url":"https://api.github.com/users/allo-media/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/allo-media/tech-blog","description":"Things we've learned hacking on them","fork":false,"url":"https://api.github.com/repos/allo-media/tech-blog","forks_url":"https://api.github.com/repos/allo-media/tech-blog/forks","keys_url":"https://api.github.com/repos/allo-media/tech-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/allo-media/tech-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/allo-media/tech-blog/teams","hooks_url":"https://api.github.com/repos/allo-media/tech-blog/hooks","issue_events_url":"https://api.github.com/repos/allo-media/tech-blog/issues/events{/number}","events_url":"https://api.github.com/repos/allo-media/tech-blog/events","assignees_url":"https://api.github.com/repos/allo-media/tech-blog/assignees{/user}","branches_url":"https://api.github.com/repos/allo-media/tech-blog/branches{/branch}","tags_url":"https://api.github.com/repos/allo-media/tech-blog/tags","blobs_url":"https://api.github.com/repos/allo-media/tech-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/allo-media/tech-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/allo-media/tech-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/allo-media/tech-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/allo-media/tech-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/allo-media/tech-blog/languages","stargazers_url":"https://api.github.com/repos/allo-media/tech-blog/stargazers","contributors_url":"https://api.github.com/repos/allo-media/tech-blog/contributors","subscribers_url":"https://api.github.com/repos/allo-media/tech-blog/subscribers","subscription_url":"https://api.github.com/repos/allo-media/tech-blog/subscription","commits_url":"https://api.github.com/repos/allo-media/tech-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/allo-media/tech-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/allo-media/tech-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/allo-media/tech-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/allo-media/tech-blog/contents/{+path}","compare_url":"https://api.github.com/repos/allo-media/tech-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/allo-media/tech-blog/merges","archive_url":"https://api.github.com/repos/allo-media/tech-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/allo-media/tech-blog/downloads","issues_url":"https://api.github.com/repos/allo-media/tech-blog/issues{/number}","pulls_url":"https://api.github.com/repos/allo-media/tech-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/allo-media/tech-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/allo-media/tech-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/allo-media/tech-blog/labels{/name}","releases_url":"https://api.github.com/repos/allo-media/tech-blog/releases{/id}","deployments_url":"https://api.github.com/repos/allo-media/tech-blog/deployments","created_at":"2017-12-21T17:26:30Z","updated_at":"2018-01-30T12:56:03Z","pushed_at":"2018-02-06T21:06:27Z","git_url":"git://github.com/allo-media/tech-blog.git","ssh_url":"git@github.com:allo-media/tech-blog.git","clone_url":"https://github.com/allo-media/tech-blog.git","svn_url":"https://github.com/allo-media/tech-blog","homepage":"http://tech.allo-media.net/","size":5507,"stargazers_count":1,"watchers_count":1,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":2,"license":null,"forks":0,"open_issues":2,"watchers":1,"default_branch":"master"}},"base":{"label":"allo-media:master","ref":"master","sha":"0254ed2232de60e61e101aa22d2cab1dafd0cbde","user":{"login":"allo-media","id":30897478,"avatar_url":"https://avatars0.githubusercontent.com/u/30897478?v=4","gravatar_id":"","url":"https://api.github.com/users/allo-media","html_url":"https://github.com/allo-media","followers_url":"https://api.github.com/users/allo-media/followers","following_url":"https://api.github.com/users/allo-media/following{/other_user}","gists_url":"https://api.github.com/users/allo-media/gists{/gist_id}","starred_url":"https://api.github.com/users/allo-media/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/allo-media/subscriptions","organizations_url":"https://api.github.com/users/allo-media/orgs","repos_url":"https://api.github.com/users/allo-media/repos","events_url":"https://api.github.com/users/allo-media/events{/privacy}","received_events_url":"https://api.github.com/users/allo-media/received_events","type":"Organization","site_admin":false},"repo":{"id":115030454,"name":"tech-blog","full_name":"allo-media/tech-blog","owner":{"login":"allo-media","id":30897478,"avatar_url":"https://avatars0.githubusercontent.com/u/30897478?v=4","gravatar_id":"","url":"https://api.github.com/users/allo-media","html_url":"https://github.com/allo-media","followers_url":"https://api.github.com/users/allo-media/followers","following_url":"https://api.github.com/users/allo-media/following{/other_user}","gists_url":"https://api.github.com/users/allo-media/gists{/gist_id}","starred_url":"https://api.github.com/users/allo-media/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/allo-media/subscriptions","organizations_url":"https://api.github.com/users/allo-media/orgs","repos_url":"https://api.github.com/users/allo-media/repos","events_url":"https://api.github.com/users/allo-media/events{/privacy}","received_events_url":"https://api.github.com/users/allo-media/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/allo-media/tech-blog","description":"Things we've learned hacking on them","fork":false,"url":"https://api.github.com/repos/allo-media/tech-blog","forks_url":"https://api.github.com/repos/allo-media/tech-blog/forks","keys_url":"https://api.github.com/repos/allo-media/tech-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/allo-media/tech-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/allo-media/tech-blog/teams","hooks_url":"https://api.github.com/repos/allo-media/tech-blog/hooks","issue_events_url":"https://api.github.com/repos/allo-media/tech-blog/issues/events{/number}","events_url":"https://api.github.com/repos/allo-media/tech-blog/events","assignees_url":"https://api.github.com/repos/allo-media/tech-blog/assignees{/user}","branches_url":"https://api.github.com/repos/allo-media/tech-blog/branches{/branch}","tags_url":"https://api.github.com/repos/allo-media/tech-blog/tags","blobs_url":"https://api.github.com/repos/allo-media/tech-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/allo-media/tech-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/allo-media/tech-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/allo-media/tech-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/allo-media/tech-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/allo-media/tech-blog/languages","stargazers_url":"https://api.github.com/repos/allo-media/tech-blog/stargazers","contributors_url":"https://api.github.com/repos/allo-media/tech-blog/contributors","subscribers_url":"https://api.github.com/repos/allo-media/tech-blog/subscribers","subscription_url":"https://api.github.com/repos/allo-media/tech-blog/subscription","commits_url":"https://api.github.com/repos/allo-media/tech-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/allo-media/tech-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/allo-media/tech-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/allo-media/tech-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/allo-media/tech-blog/contents/{+path}","compare_url":"https://api.github.com/repos/allo-media/tech-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/allo-media/tech-blog/merges","archive_url":"https://api.github.com/repos/allo-media/tech-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/allo-media/tech-blog/downloads","issues_url":"https://api.github.com/repos/allo-media/tech-blog/issues{/number}","pulls_url":"https://api.github.com/repos/allo-media/tech-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/allo-media/tech-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/allo-media/tech-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/allo-media/tech-blog/labels{/name}","releases_url":"https://api.github.com/repos/allo-media/tech-blog/releases{/id}","deployments_url":"https://api.github.com/repos/allo-media/tech-blog/deployments","created_at":"2017-12-21T17:26:30Z","updated_at":"2018-01-30T12:56:03Z","pushed_at":"2018-02-06T21:06:27Z","git_url":"git://github.com/allo-media/tech-blog.git","ssh_url":"git@github.com:allo-media/tech-blog.git","clone_url":"https://github.com/allo-media/tech-blog.git","svn_url":"https://github.com/allo-media/tech-blog","homepage":"http://tech.allo-media.net/","size":5507,"stargazers_count":1,"watchers_count":1,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":2,"license":null,"forks":0,"open_issues":2,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/allo-media/tech-blog/pulls/13"},"html":{"href":"https://github.com/allo-media/tech-blog/pull/13"},"issue":{"href":"https://api.github.com/repos/allo-media/tech-blog/issues/13"},"comments":{"href":"https://api.github.com/repos/allo-media/tech-blog/issues/13/comments"},"review_comments":{"href":"https://api.github.com/repos/allo-media/tech-blog/pulls/13/comments"},"review_comment":{"href":"https://api.github.com/repos/allo-media/tech-blog/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/allo-media/tech-blog/pulls/13/commits"},"statuses":{"href":"https://api.github.com/repos/allo-media/tech-blog/statuses/babf6457aef8b6227eb92c4c1aac8ce7e87aae7f"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"vjousse"}}