Skip to content

Instantly share code, notes, and snippets.

@hakatashi hakatashi/sig-web-11.md
Last active Nov 4, 2016

Embed
What would you like to do?
TSG 第11回Web分科会 カンペ

TSG 第11回Web分科会 カンペ

Ajaxを用いたJavaScriptによる動的通信を学ぶ。

Hello, Wocld!

以下のHTMLをコピペして適当な名前で保存し、ブラウザで開く。

<!DOCTYPE html>
<html>
	<head>
		<title>Ajax Test</title>
	</head>
	<body>
		<h1 id="result"></h1>
		<script>
			const xhr = new XMLHttpRequest();
			xhr.open('GET', 'https://api.github.com/users/hakatashi', true);
			xhr.onreadystatechange = () => {
				if (xhr.readyState === 4 && xhr.status === 200) {
					const data = JSON.parse(xhr.responseText);
					document.getElementById('result').textContent = data.bio;
				}
			};
			xhr.send();
		</script>
	</body>
</html>

「Hello, World! I'm hakatashi.」と表示されれば成功。

Ajaxとは

Asynchronous JavaScript + XML の略⋯⋯らしい。

従来(~2005年)のWebではサーバーと通信を行うのはブラウザの仕事であり、ウェブページを開いた瞬間にそのページと必要なその他のリソースを読み込みに行く以外に通信が発生することがなかった。よってサーバーに新しいデータを送信したり、サーバーからの新しい情報を表示するためには、新たにページを開いて読み込み直す必要があった。

が、XHRの登場によりJavaScriptからブラウザと同じような通信を行うことができるようになり、ページ遷移することなく同じページの中で新たにデータを送信したり取得することができるようになった。

このような、ブラウザ上のJavaScriptから非同期的に行う通信のことを総称してAjaxと呼ぶ。

Ajaxの利点

  • ほげ

XHR

XMLHttpRequestの略。長らくAjaxを行うための唯一のAPIだった。

名前にXMLとついているのは、XML全盛期であった古の時代の名残であり、実際にはXMLに限らずテキストでもHTMLでもJSONでも画像でも、とりあえずブラウザからアクセスできるデータなら何でも通信できる。

古代時代に実装されたものということもあって、そのAPIは複雑で非常に扱いづらい。また非標準の実装がたくさん存在する。先ほどのコードを解説すると、

// コンストラクタでXHRを初期化する
const xhr = new XMLHttpRequest();

// 通信内容の初期化。第3引数は非同期で実行するかを表す。
xhr.open('GET', 'https://api.github.com/users/hakatashi', true);

// readystatechangeイベントにハンドラを登録する。
// readyStateにはXHRの現在の状態が記録されている。
xhr.onreadystatechange = () => {
	// readyState === 4 はDONEを表す
	if (xhr.readyState === 4 && xhr.status === 200) {
		// JSONデータをパースする
		const data = JSON.parse(xhr.responseText);
		// データをDOMに格納
		document.getElementById('result').textContent = data.bio;
	}
};

// 送信開始
xhr.send();

となる。POSTしたりLong-Pollingを実装したりするとさらに複雑になる。

jQuery.ajax

万能ライブラリjQueryの大量にある機能の一つ。複雑怪奇なXHRのAPIをラップしたもの。

上と(ほぼ)同じ処理をjQueryを用いて書くと以下のようになる。

$.ajax({
	url: 'https://api.github.com/users/hakatashi',
	method: 'GET',
	json: true,
}).done(data => {
	document.getElementById('result').textContent = data.bio;
});

// もしくは
$.get('https://api.github.com/users/hakatashi', {
	json: true,
}).done(data => {
	document.getElementById('result').textContent = data.bio;
});

// もしくは
$.getJSON('https://api.github.com/users/hakatashi').done(data => {
	document.getElementById('result').textContent = data.bio;
});

Fetch API

ブラウザのAPIに最近実装されつつあるもの。既存のXHRを置き換える目的で開発された。

jQueryを用いなくてもAjax処理を簡潔に、そしてPromise的に書くことができる。

fetch('https://api.github.com/users/hakatashi')
.then(response => response.json())
.then(data => {
	document.getElementById('result').textContent = data.bio;
});

実習

フォト蔵APIを使って写真を検索するフォームを作ろう。

フォト蔵APIは外部サイトから叩けないようになっているので、photozou.hakatashi.comにプロキシサーバーを用意した。 (セキュリティ的によくないので実習が終わったら落とします)

例えば「猫」で画像検索するには、以下のURLを(GETで)叩く。 http://photozou.hakatashi.com/rest/search_public.json?keyword=%E7%8C%AB

ベースとして、以下のHTMLを使用する。 https://gist.github.com/hakatashi/6fab7eb84530eeedae5bbf8c3d065381

ヒント

  • それぞれの画像をHTMLに変換するときはtemplate関数を使う。
  • 文字列をURLに突っ込むときはencodeURIComponent関数でエスケープする。
  • 非同期処理の実行順序に注意!

余力があったら

  • ページングを実装
  • フォト蔵APIの他のオプションを指定できるようにする。
    • copyrightオプションとか
  • 他の画像検索APIと組み合わせて、結果を同時に表示する
    • 例えばTumblr APIとか。
      • APIキーを取得してJSONPでリクエストする必要がある。jQueryのjsonpオプションを使うのが楽。
  • XSS対策

参考実装

https://gist.github.com/hakatashi/5d64a73d9cd113651d0148a1ec26d802

  • 検索機能
  • XSS対策
  • ページング(オートページャ)

まで実装してます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.