はしくれエンジニアもどきのメモ

情報系技術・哲学・デザインなどの勉強メモ・備忘録です。

「2日でできる JavaScriptTraining」をやってみた(非同期通信)

「2日でできる JavaScriptTraining」をやってみた(非同期通信)

mixi の「2日でできる JavaScriptTraining」をやってみたのでメモ。 今回は、非同期通信系をまとめておきます。

github.com

環境

動作したバージョンを以下にに書いておく。

  • Chrome 46.0.2490.86 m (64-bit)

  • Node.js v5.0.0

    • npm 3.4.1

      • gulp version 3.9.0

      • bower 1.6.5

5.非同期処理を書くトレーニング

setTimeout

setTimeout の処理は、 他の処理が終わってから実行されるので、 delay が0[ms]でも後から処理される。

下の処理では、2 → 1 の順で処理される。


setTimeout(function() {
  console.log(1);
}, 0);
console.log(2);

サーバとの通信

個人的にはよく、 jQuery.ajax() を使っていたが。 新しいAPIとして Fetch API があるらしい。

Promise を使った非同期処理

.then(function(response){}) で、 正常にレスポンスを受け取った場合の処理を書ける。 response.json()json形式の値を、 response.text() でテキスト形式の値を 取得できる。

.catch(function(error){}) でエラーの場合の処理を書ける。


fetch('/users.json')
.then(function(response) {
  return response.json();
})
.then(function(json) {
  console.log('parsed json', json);
})
.catch(function(error) {
  console.error('parsing failed', error);
});

.then のレスポンスの値は、 resolveハンドラーで指定できる。


var promise = Promise.resolve('resolved!');
promise.then(function(msg) {
  console.log(msg); // 'resolved!' が返る。
});

.catch のレスポンスの値は、 rejectハンドラーで指定できる。


var promise = Promise.reject('rejected!');
promise.catch(function(msg){
  console.log(msg); // rejected!
});

Promise による並行非同期処理

複数のAPI からすべてのレスポンスを受け取ってから 処理したい場合は、Promise.all([]) を使う。


Promise.all([
  fetch('/api/foo'),
  fetch('/api/bar')
])
.then(function(responses) {
  var responseFoo = responses[0];
  var responseBar = responses[1];
});

複数のAPI(Promise)のうち最も早くレスポンスされた値のみを処理したい場合は、 Promise.race([]) を使う。


var promise = Promise.race([promise1, promise2, promise3]);
promise.then(function(msg){
  console.log(msg); // 一番早くレスポンスあったものが返ってくる。
});

Promise による直列非同期処理

.then() で繋げていくことで、 逐次的に処理できる。

下記コードであれば、 foo, bar, buz の順で実行される。


fetch('/api/foo')
.then(function(res){
  console.log('foo ', res);
})
.then(function() { return fetch('/api/bar'); })
.then(function(res){
  console.log('bar ', res);
})
.then(function() { return fetch('/api/buz'); })
.then(function(res){
  console.log('buz ', res);
});

GitHub API を使ってみる

Github API の endpoint は、 https://api.github.com/

Github に登録している組織のorganization の情報を取得

詳細:https://developer.github.com/v3/orgs/#get-an-organization


GET /orgs/:org

となっているので、 https://api.github.com/orgs/組織名 で取得できる。

Fetch API を使用する場合、以下のコードで取得できる。 (例:orgs: github のorganization を取得。)


var endpoint = 'https://api.github.com/';
var orgs = 'orgs/'
var org = 'github';
var orgFetch = fetch([endpoint+orgs+org])
.then(function(res){
  return res.json();
})
.then(function(json){
  console.log(json);
  return json;
});

github のorganization 情報は以下のようになる。


{
  "login": "github",
  "id": 9919,
  "url": "https://api.github.com/orgs/github",
  "repos_url": "https://api.github.com/orgs/github/repos",
  "events_url": "https://api.github.com/orgs/github/events",
  "members_url": "https://api.github.com/orgs/github/members{/member}",
  "public_members_url": "https://api.github.com/orgs/github/public_members{/member}",
  "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=3",
  "description": "How people build software.",
  "name": "GitHub",
  "company": null,
  "blog": "https://github.com/about",
  "location": "San Francisco, CA",
  "email": "support@github.com",
  "public_repos": 122,
  "public_gists": 0,
  "followers": 0,
  "following": 0,
  "html_url": "https://github.com/github",
  "created_at": "2008-05-11T04:37:31Z",
  "updated_at": "2015-11-08T20:21:57Z",
  "type": "Organization"
}

リポジトリの情報を取得

詳細:https://developer.github.com/v3/repos/#get


GET /repos/:owner/:repo

となっているので、 https://api.github.com/repos/レポジトリ所有者/レポジトリ名 で取得できる。

試しに、リポジトリであるoctocat/Hello-World · GitHub

リポジトリ情報を取得してみる。 

github.com

Fetch APIを使用したコードは以下のようになる。


var endpoint = 'https://api.github.com/';
var repos = 'repos/';
var owner = 'octocat';
var repo = 'Hello-World';
var repoFetch = fetch([endpoint + repos + owner + repo])
.then(function(res){
  return res.json();
})
.then(function(json){
  console.log(json);
  return json;
});

返ってくる値は以下のようになる。


{
  "id": 1296269,
  "name": "Hello-World",
  "full_name": "octocat/Hello-World",
  "owner": {
    "login": "octocat",
    "id": 583231,
    "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=3",
    "gravatar_id": "",
    "url": "https://api.github.com/users/octocat",
    "html_url": "https://github.com/octocat",
    "followers_url": "https://api.github.com/users/octocat/followers",
    "following_url": "https://api.github.com/users/octocat/following{/other_user}",
    "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
    "organizations_url": "https://api.github.com/users/octocat/orgs",
    "repos_url": "https://api.github.com/users/octocat/repos",
    "events_url": "https://api.github.com/users/octocat/events{/privacy}",
    "received_events_url": "https://api.github.com/users/octocat/received_events",
    "type": "User",
    "site_admin": false
  },
  "private": false,
  "html_url": "https://github.com/octocat/Hello-World",
  "description": "This your first repo!",
  "fork": false,
  "url": "https://api.github.com/repos/octocat/Hello-World",
  "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks",
  "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
  "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
  "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams",
  "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks",
  "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
  "events_url": "https://api.github.com/repos/octocat/Hello-World/events",
  "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}",
  "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}",
  "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags",
  "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
  "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
  "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
  "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
  "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
  "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages",
  "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers",
  "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors",
  "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers",
  "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription",
  "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}",
  "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
  "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}",
  "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
  "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}",
  "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
  "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges",
  "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
  "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads",
  "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}",
  "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}",
  "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}",
  "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
  "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}",
  "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}",
  "created_at": "2011-01-26T19:01:12Z",
  "updated_at": "2015-11-11T12:17:16Z",
  "pushed_at": "2015-11-05T07:01:26Z",
  "git_url": "git://github.com/octocat/Hello-World.git",
  "ssh_url": "git@github.com:octocat/Hello-World.git",
  "clone_url": "https://github.com/octocat/Hello-World.git",
  "svn_url": "https://github.com/octocat/Hello-World",
  "homepage": "",
  "size": 578,
  "stargazers_count": 1402,
  "watchers_count": 1402,
  "language": null,
  "has_issues": true,
  "has_downloads": true,
  "has_wiki": true,
  "has_pages": false,
  "forks_count": 1119,
  "mirror_url": null,
  "open_issues_count": 152,
  "forks": 1119,
  "open_issues": 152,
  "watchers": 1402,
  "default_branch": "master",
  "network_count": 1119,
  "subscribers_count": 1740
}

リポジトリを検索して該当のリポジトリ情報を取得

検索は、search でクエリを指定することができる。

詳細:Search | GitHub API


GET /search/repositories
  • パラメータ q

    パラメータq=検索したい文字列で検索できる。 また、プログラミング言語を指定する場合は q=検索したい文字列+language:言語 となる。

  • パラメータ sort

    fork数やスターの数などソートの基準を指定できる。 sort=stars でスターの数で検索結果をソートする。

  • パラメータ order

    降順か昇順を指定する。 降順の場合、order=desc、 昇順の場合、order=asc

プログラミング言語を指定して、 最もスター数の多いレポジトリの情報を返す コードは以下。


function getRepositoryFetch(language){
  var endpoint = 'https://api.github.com/';
  var search = 'search/repositories';
  var sort = 'stars';
  var order = 'desc';
  var queries = '?q=language:' + language + '&sort=' + sort + '&order=' + order;

  return
  fetch([endpoint+search+queries])
  .then(function(res){
    return res.json();
  })
  .then(function(json){
    var item = json.items[0]; // Array items に検索結果が格納
      console.log(item);
      return item;
  });
}

var popularRepos = getRepositoryFetch('C');

返ってくる結果は以下(適当に抜粋)。 C言語のスター数1位は、Linux らしい。


{
  id: 2325298,
  name: "linux",
  full_name: "torvalds/linux",
  forks: 10827,
  forks_count: 10827,
  html_url: "https://github.com/torvalds/linux",
  language: "C",
  size: 2478175,
  stargazers_count: 27343,
  stargazers_url: "https://api.github.com/repos/torvalds/linux/stargazers",
  url: "https://api.github.com/repos/torvalds/linux",
  watchers: 27343,
  watchers_count: 27343
}