axiosのthenやcatchがわからない。そしてPromiseやasync/awaitとかも出てきてしまうから余計に頭が混同してまう。
今回は、ちょっと一旦その単語調べさせて〜と半べそかきながら参考文献を読み漁って脳内パッチワークをしたログになります。#いい歳して半べそかくな。
axiosとは
axiosとはブラウザやnode.js上で動くPromiseベースのHTTPクライアントです。非同期にHTTP通信を行いたいときに容易に実装できます。
でた、Promise。HTTPクライアントってことは、サーバーにリクエストをなげる何かってことなのかな。
どうやって使うのか
そうやらgetとpostでサーバーに対してリクエストを投げられるらしい。
GET通信
GET通信はaxios.getメソッドを使用する。
第一引数にパラメータ付きのURLを指定し、
.then()で通信が成功した際の処理を書いている。
.catch()はエラーにの処理を書く。
.finally()は通信が成功しても失敗しても常に実行される。
1
2
3
4
5
6
7
8
9
10
|
axios
.get('/user?ID=12345')
.then(function (response) { // handle success
console.log(response);
})
.catch(function (error) { // handle error
console.log(error);
})
.finally(function () { // always executed
});
|
POST通信
POST通信はaxios.postメソッドを使用する。
1
2
3
4
5
|
axios
.post('/user', { firstName: 'subaru', lastName: 'nakano'})
.then(function (response) { console.log(response);})
.catch(function (error) { console.log(error);
});
|
第2引数に送信したいデータを指定することでPOST送信できる。
postアクションが行われたときに、/userパスに第二引数が渡されるようになっている。
例えばログインアクションを実装したい時に、postは以下のように使う。
Vuexに入れているからmutationに対して変更をcommitする流れを記述している。
1
2
3
4
5
6
7
8
9
10
11
|
const actions = {
loginUser({ commit }, user) {# ...1
axios
.post('sessions', user) # ...2
.then((res) => {#...3
commit('setAuthUser', res.data);#...4
router.push({ name: 'PreliquoTop' });
alert('ログインに成功しました');
})
.catch((err) => console.log(err));
}
|
第一引数にcommitを取り、第二引数のデータをmutationにコミットできるようにしている。
sessionsコントローラーのpostアクション(createアクション)に対して、userをpostしている。
Promiseのresolveの省略形。成功したときの処理を書いている。。
postアクションが成功したら、そのセッションデータがsetAuthUserに渡るようになっている
Promise
処理の順序に「お約束」を取り付けることができるもの、処理を待機することや、その結果に応じて次の処理をすることお約束するもの。
Promiseでは、処理されている状態を表す三つのメソッドがある。
pending: 未解決 (処理が終わるのを待っている状態)
resolved: 解決済み (処理が終わり、無事成功した状態)
rejected: 拒否 (処理が失敗に終わってしまった状態)
Promiseの基本形は下記のように書く。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
function 非同期的な関数(成功時コールバック, 失敗時コールバック) {
if (...) {
成功時コールバック(成果)
} else {
失敗時コールバック(問題)
}
}
// ↓executor
new Promise(function (resolve, reject) {
非同期的な関数(
(成果) => resolve(成果), // 成功時コールバック関数
(問題) => reject(問題), // 失敗時コールバック関数
)
})
|
ここで使用されているPromiseインスタンスを抜粋すると、下記のような書き方になっている。
1
|
const promise = new Promise((resolve, reject) => {});
|
{}の中身がresolveした場合は、.thenの中身が実行され、rejectされた場合は.catchの中身が実行される。
async/await
asyncとは
asyncは非同期関数を定義する関数宣言であり、関数の頭につけることで、Promiseオブジェクトを返す関数にすることができます
非同期関数を定義する関数宣言のこと。
以下のように関数の前にasyncを宣言することにより、非同期関数(async function)を定義できる。
1
|
async function sample() {}
|
awaitとは
awaitは、Promiseオブジェクトが値を返すのを待つ演算子です。awaitは必ず、async function内で使います
async function内でPromiseの結果(resolve、reject)が返されるまで待機する(処理を一時停止する)演算子のこと
以下のように、関数の前にawaitを指定すると、その関数のPromiseの結果が返されるまで待機する。
1
2
3
4
5
6
|
async function sample() {
const result = await sampleResolve();
// sampleResolve()のPromiseの結果が返ってくるまで以下は実行されない
console.log(result);
}
|
まとめると、
- await → Promiseの値が取り出されるまで待つ。
- async → awaitキーワードを使っている関数のあたまに付ける必要がある。
- asyncとawaitを使うと、.thenと.catchを省略できるのでコードがスッキリする。
async/awaitを使った場合と使わなかった場合の非同期処理を比較
1
2
3
4
5
6
7
8
9
10
11
12
|
function getServerStatusCode() {
return new Promise(function(resolve, reject) {
axios
.get("<https://httpbin.org/status/200>")
.then(response => resolve(response.status))
.catch(error => reject(error.response.status))
});
}
getServerStatusCode()
.then(statusCode => console.log("生きてる", statusCode))
.catch(statusCode => console.error("死んでる", statusCode))
|
1
2
3
4
5
6
7
8
9
10
11
|
async function getServerStatusCode() {
try {
return (await axios.get("<https://httpbin.org/status/500>")).status
} catch (error) {
throw error.response.status
}
}
getServerStatusCode()
.then(statusCode => console.log("生きてる", statusCode))
.catch(statusCode => console.error("死んでる", statusCode))
|
チェーンさせることもできる
.thenを組み合わせることで、「1番目の処理が成功したら、2番目の処理を実行させる」といったことも可能になる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
const promise = new Promise((resolve, reject) => {
resolve("ヤッホー");
})
.then((val) => {
console.log(`then1: ${val}`);
return val;
})
.catch((val) => {
console.log(`catch: ${val}`);
return val;
})
.then((val) => {
console.log(`then2: ${val}`);
});
#出力結果
#then1: ヤッホー
#then2: ヤッホー
|
catchの中身はエラー時のみなので、今回はthen1とthen2が表示されている。
連続した非同期処理(async/await構文)
awaitを利用すれば、then()で処理を繋げなくても連続した非同期処理が書ける。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
function sampleResolve(value) {
return new Promise(resolve => {
setTimeout(() => {
resolve(value);
}, 1000);
})
}
async function sample() {
return await sampleResolve(10) * await sampleResolve(10) + await sampleResolve(20);
}
async function sample2() {
const a = await sampleResolve(10);
const b = await sampleResolve(10);
const c = await sampleResolve(20);
return a * b + c;
}
sample().then((v) => {
console.log(v); // => 120
});
sample2().then((v) => {
console.log(v); // => 120
});
|
まとめ
Promise構文を使うと、javascriptに処理する順序を与えることができる。
.thenを繋げるコードは綺麗じゃない。そんな時はasync/awaitを使う。
asyncが文頭にあるfunctionはPromiseのレスポンスが返るまでawait内の処理を実行しない。
ざっくり、Promiseを使うとconsole.logの順番を制御できるんだな〜と認識できた。axios.postした後の順番を制御するためにpromiseが使われているのかな?アプリ制作が終わる頃にはマスターしてたい!
参考
アクション | Vuex
async/await 入門(JavaScript) - Qiita
Promise - JavaScript | MDN
【ES6】 JavaScript初心者でもわかるPromise講座 - Qiita
Promiseの使い方、それに代わるasync/awaitの使い方 - Qiita
async/await 入門(JavaScript) - Qiita
【Ajax】axiosを使って簡単にHTTP通信 | Will Style Inc.|神戸にあるウェブ制作会社