「2日でできる JavaScriptTraining」をやってみた(非同期通信)
「2日でできる JavaScriptTraining」をやってみた(非同期通信)
mixi の「2日でできる JavaScriptTraining」をやってみたのでメモ。 今回は、非同期通信系をまとめておきます。
環境
動作したバージョンを以下にに書いておく。
-
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 があるらしい。
-
Fetch API
策定中の新しい仕様。 おそらく今後の使用が増えていくAPI。
Promise
を返す。仕様(日本語訳): Fetch Standard (日本語訳)
-
XTMLRequest
使いやすくラップされているjQuery の
$.ajax()
をよく使う。 返り値としてDeffered
が返り、結果Promiseが使える。
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
のリポジトリ情報を取得してみる。
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 でクエリを指定することができる。
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
}
参考リンク