[英]Firebase v9 Firestore: Add 2 documents one by one
首先,我想向 Firestore 添加一個文檔:
await setDoc(product, docData, {
merge: true
});
一旦我 100% 確定文檔已成功寫入,我想添加/更新另一個文檔:
const products_array_snap = await getDoc(products_array);
if (products_array_snap.exists()) {
await updateDoc(products_array, {
products_array: arrayUnion(productSKU)
});
console.log("Product array exists:", products_array_snap.data());
} else {
await setDoc(products_array, {
products_array: arrayUnion(productSKU),
products_default: productSKU
});
console.log("No product array!");
}
如何重寫此代碼以處理錯誤並確保兩個文檔正確設置在一起?
因為您的操作依賴於服務器的狀態(感謝products_default
),所以您需要將整個事情包裝在一個事務中。 事務只會以全有或全無(原子)方式對數據庫進行更改,因此您可以保證如果它解決了,您的產品文檔和產品數組都將正確更新。
這些是以下塊使用的變量:
import { runTransaction, getFirestore, doc, collection } from "firebase/firestore";
const db = getFirestore();
const products_array_ref = doc(db, 'docIds/products');
const product_ref = doc(collection(db, 'products'));
const product_id = product_ref.id;
const product_data = { /* ... */ };
要使用runTransaction
,您需要傳入您正在使用的 Firestore 實例以及一個“更新函數”,該函數使用Transaction
將更改runTransaction
數據庫。 重要的是要記住,如果在您處理數據時服務器端的數據發生變化(例如添加/刪除了另一個產品),則可能會多次調用更新函數。
在這個函數中,你必須首先下拉你的事務所依賴的所有依賴項。 如果需要一次讀取多個文檔,可以使用Promise.all()
並行抓取它們。 擁有所有依賴項后,您可以開始將要提交到服務器的更改排隊。 如果你從更新函數返回一個值,它會在它最終解析時從runTransaction
傳遞出去。 您可以使用它來跟蹤嘗試了多少次,如果您自願中止交易,原始文檔是否存在等。如果由於爭用或其他問題而無法寫入交易, runTransaction
將拒絕其 Promise適當的錯誤。
對於您的用例,您可以像這樣編寫邏輯:
const products_array_existed = await runTransaction(db, async (transaction) => {
// dependencies
const products_array_snap = await transaction.get(products_array_ref);
// queue changes
transaction.set(product_ref, product_data, { merge: true });
if (products_array_snap.exists()) {
transaction.update(
products_array_ref,
{ products_array: arrayUnion(product_id) }
);
} else {
transaction.set(
products_array_ref,
{
products_array: arrayUnion(product_id),
products_default: product_id
},
{ merge: true }
);
}
// set return value
return products_array_snap.exists();
});
console.log(`Products array ${products_array_existed ? "already existed" : "was created"}.`);
或者
const products_array_existed = await runTransaction(db, async (transaction) => {
// dependencies
const products_array_snap = await transaction.get(products_array_ref);
const products_array_change = {
products_array: arrayUnion(product_id),
...(products_array_snap.exists() ? {} : { products_default: product_id })
}
// queue changes
transaction.set(product_ref, product_data, { merge: true });
transaction.set(products_array_ref, products_array_change, { merge: true });
// set return value
return products_array_snap.exists();
});
console.log(`Products array ${products_array_existed ? "already existed" : "was created"}.`);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.