有了 Cloud Functions,您可以在
Firebase Realtime Database,則不需要更新用戶端程式碼。
Cloud Functions 可讓您透過完整管理功能執行 Realtime Database 作業
權限,並確認所有 Realtime Database 變更都經過處理
個別。您可以透過以下位置進行 Firebase Realtime Database 項變更:
DataSnapshot
或透過 Admin SDK 即可。
在一般生命週期中,Firebase Realtime Database 函式會執行以下操作:
- 等待變更特定 Realtime Database 位置。
- 在事件發生時觸發並執行其工作 (請參閱我可以做些什麼? 你使用的是「Cloud Functions」嗎?舉例來說 用途)
- 接收包含所儲存資料快照的資料物件 指定文件。
觸發 Realtime Database 函式
為 Realtime Database 事件建立新函式
使用 functions.database
。目的地:
控制函式觸發的時機、指定其中一個事件處理常式,以及
指定 Realtime Database 路徑,用於監聽事件。
設定事件處理常式
函式可讓您處理兩種精細程度的 Realtime Database 事件; 可監聽特定的建立、更新 或刪除路徑的任何類型變更 Cloud Functions 支援 Realtime Database 的以下事件處理常式:
onWrite()
:在 Realtime Database 中建立、更新或刪除資料時觸發。onCreate()
:在 Realtime Database 中建立新資料時觸發。onUpdate()
,會在 Realtime Database 中更新資料時觸發。onDelete()
:從 Realtime Database 刪除資料時觸發。
指定執行個體和路徑
如要控管函式觸發的時機和位置,請呼叫 ref(path)
指定路徑,並視需要指定 Realtime Database 例項
搭配 instance('INSTANCE_NAME')
。如果您不
指定執行個體,函式就會部署至預設的 Realtime Database 執行個體,
Firebase 專案。例如:
- 預設 Realtime Database 執行個體:
functions.database.ref('/foo/bar')
- 執行個體名稱為「my-app-db-2」:
functions.database.instance('my-app-db-2').ref('/foo/bar')
這些方法會引導您的函式處理內部特定路徑的寫入作業
Realtime Database 例項。路徑規格會與接觸路徑的「所有」寫入作業相符。
包括寫入
呈現的成就如果將路徑設為
函式為 /foo/bar
,會比對以下兩個位置的事件:
/foo/bar
/foo/bar/baz/really/deep/path
無論是哪一種情況,Firebase 都會解讀事件發生在 /foo/bar
,
而事件資料包括
新舊資料 (/foo/bar
)如果事件資料可能相當龐大
考慮在更深層的路徑中使用多個函式
函式。如要獲得最佳效能,請僅要求可能的最深層級資料。
您可以在路徑元件前後加上捲軸,將路徑元件指定為萬用字元
方括號;ref('foo/{bar}')
與 /foo
的任何子項相符。這些屬性的值
萬用字元路徑元件位於
EventContext.params
敬上
物件物件本例中的值是
context.params.bar
。
使用萬用字元的路徑可以與單一寫入內容中的多個事件進行比對。 將
{
"foo": {
"hello": "world",
"firebase": "functions"
}
}
比對路徑 "/foo/{bar}"
兩次:一次與 "hello": "world"
以及 "firebase": "functions"
的通訊。
處理事件資料
處理 Realtime Database 事件時,傳回的資料物件會是
DataSnapshot
。
如果是 onWrite
或 onUpdate
事件,則
第一個參數是含有兩個快照的 Change
物件
代表資料狀態的
觸發事件對於 onCreate
和 onDelete
事件,
傳回的資料物件是建立或刪除資料的快照。
在這個範例中,函式會擷取 並將該位置的字串轉換成大寫, 並將經過修改的字串寫入資料庫:
// Listens for new messages added to /messages/:pushId/original and creates an // uppercase version of the message to /messages/:pushId/uppercase exports.makeUppercase = functions.database.ref('/messages/{pushId}/original') .onCreate((snapshot, context) => { // Grab the current value of what was written to the Realtime Database. const original = snapshot.val(); functions.logger.log('Uppercasing', context.params.pushId, original); const uppercase = original.toUpperCase(); // You must return a Promise when performing asynchronous tasks inside a Functions such as // writing to the Firebase Realtime Database. // Setting an "uppercase" sibling in the Realtime Database returns a Promise. return snapshot.ref.parent.child('uppercase').set(uppercase); });
存取使用者驗證資訊
來源:EventContext.auth
和 EventContext.authType
,
您可以存取
針對觸發事件的使用者資訊 (包括權限)
函式這對於強制執行安全性規則、
讓您的函式能根據使用者的
權限等級:
const functions = require('firebase-functions/v1');
const admin = require('firebase-admin');
exports.simpleDbFunction = functions.database.ref('/path')
.onCreate((snap, context) => {
if (context.authType === 'ADMIN') {
// do something
} else if (context.authType === 'USER') {
console.log(snap.val(), 'written by', context.auth.uid);
}
});
您也可以利用使用者驗證資訊來「冒用」身分使用者 並代表使用者執行寫入作業請務必刪除 應用程式執行個體,如下所示:
exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
.onCreate((snap, context) => {
const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
appOptions.databaseAuthVariableOverride = context.auth;
const app = admin.initializeApp(appOptions, 'app');
const uppercase = snap.val().toUpperCase();
const ref = snap.ref.parent.child('uppercase');
const deleteApp = () => app.delete().catch(() => null);
return app.database().ref(ref).set(uppercase).then(res => {
// Deleting the app is necessary for preventing concurrency leaks
return deleteApp().then(() => res);
}).catch(err => {
return deleteApp().then(() => Promise.reject(err));
});
});
讀取先前的值
Change
物件有
before
屬性,讓您查看儲存在Realtime Database 之前
活動。before
屬性會傳回 DataSnapshot
,其中所有
方法 (例如
val()
和
exists()
)。
參照先前的值您可以使用下列任一方法
原始 DataSnapshot
,或是參閱
after
資源。任何 Change
上的這個屬性,是另一個代表 DataSnapshot
資料在事件發生「之後」的狀態。
例如,使用 before
屬性可確保只有函式
大寫文字:
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onWrite((change, context) => {
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
// Grab the current value of what was written to the Realtime Database.
const original = change.after.val();
console.log('Uppercasing', context.params.pushId, original);
const uppercase = original.toUpperCase();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
// Setting an "uppercase" sibling in the Realtime Database returns a Promise.
return change.after.ref.parent.child('uppercase').set(uppercase);
});