8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

$.ajaxから$httpに乗り換えて気がついたこと

Last updated at Posted at 2016-12-23

##動機##
AngularJSでアプリケーションを構築しているのにもかかわらず、
HTTPリクエストをjQueryに頼っていた僕ですが、
幾度もチームメンバーからの冷ややかな目線を感じてましたので、
$httpに乗り換えてやろうと決意しました。

##まずは$.ajaxコードを確認してみましょう。##

network.js
let queries = {
	"name": "Donald John Trump",
	"birthday": "1946-06-14",
	"money": NaN
}

$.ajax({
	type: "POST",
	url: "https://example.com/api/action",
	data: queries,
	dataType: "json",
	success: function (response, status, xhr) {
		//成功
	},
	error: function (XMLHttpRequest, textStatus, errorThrown) {
		//失敗
	}
});

うん、実に単純、これは手間かからなそうだ。
かっこつけてES6使ったろ(ドヤ顔

##早速$httpに書き換えましょう##

network.js
let queries = {
	"name": "Donald John Trump",
	"birthday": "1946-06-14",
	"money": NaN
}

$http({
	method: "POST",
	url: "https://example.com/api/action",
	data: queries,
	responseType: "json"
}).then(
	(response) => {
		//成功
	}, 
	(errors) => {
		//失敗
	}
);

これは、ほぼ一緒だな、楽勝すぎる。
早速ビルドして送ってみましょう!

##Responseを確認##

400 Bad Request

むぅ...なるほど、
一つだけ言えるのは、
僕はこの数字が嫌いだ。

そこでAPIから帰ってきたメッセージを読んでみると、
"message": "不正なパラメーターです"

ご親切にありがたいですね、リクエストの中身を見てみましょう。

##Request Dataを確認##

$httpの場合
"name": "Donald John Trump",
"birthday": "1946-06-14",
"money": NaN

あれ?
一見なんの変哲も無いdataなんですが...
$.ajax時代のものと比較してみましょう!

$.ajaxの場合
name=Donald John Trump&birthday=1946-06-14&money=NaN

あっ...これは...まさかjsonで送っているとは、
粋なことしてくれるなぁ
仕方が無い、headerを書き換えよう

##再度チャレンジ##

network.js
// ...

$http({
	method: "POST",
	url: "https://example.com/api/action",
	headers: {
		//ヘッダーに追加してあげましょう
		'Content-Type': 'application/x-www-form-urlencoded'
	},
	data: queries,
	responseType: "json"
}).then(
	(response) => {
		//成功
	}, 
	(errors) => {
		//失敗
	}
);

さー、こい。

##Responseを確認(2度目)##

400 Bad Request

"message": "不正なパラメーターです"

なるほど。
デジャブでしょうか。
再度リクエストの中身を確認しましょう。

デジャブ
"name": "Donald John Trump",
"birthday": "1946-06-14",
"money": NaN

これはあれかね、
Content-TypeをAngularは見ていないのかね!?
おばかさんなのかね!?(半ギレ

##とりあえず解決(?)##

仕方が無い、手動で変換して差し上げましょう

network.js
// ...

$http({
	// ...
	data: queryString.stringify(queries),
	// ...
);

let queryString = {
	parse: (text = location.search.substr(1), isDecode = false) => {
		const decode = (isDecode) ? decodeURIComponent : a => a;
		return text.split('&').reduce((obj, v) => {
			var pair = v.split('=');
			obj[pair[0]] = decode(pair[1]);
			return obj;
		}, {});
	},
	stringify: (value, isEncode = false) => {
		const encode = (isEncode) ? encodeURIComponent : a => a;
		return Object.keys(value).map(key => `${key}=${encode(value[key])}`).join('&');
	},
};

これで無事に動きました。
めでたし、めでたし。

って言いたいところですが、
これをAngularがサポートしてくれないわけが無い、
きっと僕の知らない魔法がどこかあるはず!

##結論##

  • Angularはhttpリクエスト時にjsonでのやり取りを推奨している (公式ドキュメントでも明記)
  • $httpはおバカである or 僕がおバカである
  • ES6は使ってて気持ちが良い
  • 僕は400番が嫌いだ
  • jQuery($.ajax)の方が楽
  • :bride_with_veil: [追伸] $httpParamSerializerJQLike で解決!:bride_with_veil:

何か他に文明の利器は無いのでしょうか、
ちなみに他のhttpリクエスト系ライブラリーは今の所使う予定無いです。
なにかいい情報がありましたらご教授願いたいです...m(_ _)m

##追伸##
コメントでいただいた通り、 $http のドキュメントでPOSTされたものは全てJSONにしてやるぞ!と書いてありましたねーむぅ。
そして同じく頂いたコメント通りに $httpParamSerializerJQLike 実装をしたら無事にできました!
\(^〇^)/アリガタヤアリガタヤ\(^〇^)/

8
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?