はじめに
Firebaseのデータストアの1つであるFirestoreの公式ドキュメントのサンプルコードが全てPromiseチェーンになっているので、一部のコードをasync/awaitで書き直してみます。
Promiseチェーンとは
var docRef = db.collection("cities").doc("SF");
docRef.get().then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
上記のような then で非同期処理の結果を受け取る方法をPromiseチェーンと呼びます(正式名称かは不明)。
この記述を行うと、連続して非同期処理を行った時にコードの可読性が低下する要因となります。
例えば、非同期処理が3連続すると以下のようなコードになります。
var docRef = db.collection("cities").doc("SF");
var docRef2 = db.collection("cities").doc("LA");
var docRef3 = db.collection("cities").doc("DC");
docRef.get().then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
// データがなかった場合、docRef2のデータを取得する
docRef2.get().then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
// データがなかった場合、docRef3のデータを取得する
docRef3.get().then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
})
}
}).catch((error) => {
console.log("Error getting document:", error);
});
}
}).catch((error) => {
console.log("Error getting document:", error);
});
このように連続したPromiseチェーンはコードのネストが深くなりやすく、可読性が低くなります。
ドキュメントを取得する
公式ドキュメントのコード
var docRef = db.collection("cities").doc("SF");
docRef.get().then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
async/awaitを使用したコード
var docRef = db.collection("cities").doc("SF");
const getDoc = async() => {
try {
const doc = await docRef.get();
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
} catch(error) {
console.log("Error getting document:", error);
}
}
// この処理は非同期で実行される
getDoc();
3連続した非同期処理をasync/awaitに書き換える
var docRef = db.collection("cities").doc("SF");
var docRef2 = db.collection("cities").doc("LA");
var docRef3 = db.collection("cities").doc("DC");
const getDoc = async() => {
try {
const doc = await docRef.get();
if (doc.exists) {
console.log("Document data:", doc.data());
return;
}
// doc.data() will be undefined in this case
console.log("No such document!");
// データがなかった場合、docRef2のデータを取得する
const doc2 = await docRef2.get();
if (doc.exists) {
console.log("Document data:", doc2.data());
return;
}
// doc.data() will be undefined in this case
console.log("No such document!");
// データがなかった場合、docRef3のデータを取得する
const doc3 = await docRef3.get();
if (doc.exists) {
console.log("Document data:", doc3.data());
return;
}
// doc.data() will be undefined in this case
console.log("No such document!");
} catch(error) {
console.log("Error getting document:", error);
}
}
// この処理は非同期で実行される
getDoc();
Promiseチェーンが1つの場合は、ネストがあまり深くならないのでasync/awaitの恩恵をあまり感じませんが、複数の処理を実行する時は、ネストが深くなるのを抑えてくれます。
コレクションから複数のドキュメントを取得する
公式ドキュメントのコード
db.collection("cities").where("capital", "==", true)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
async/awaitを使用したコード
const getDocs = async() => {
try {
const querySnapshot = await db.collection("cities").where("capital", "==", true);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
})
} catch(error) {
console.log("Error getting documents: ", error);
}
}
// この処理は非同期で実行される
getDocs();
まとめ
Firebaseのコードは全てPromiseチェーンで記述されているため、何も考えずにコードを書いていくと、ネストが深くなりがちです。
async/awaitを使用して、ネストが少ないコードを心がけましょう!