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 ในระดับความเฉพาะเจาะจง 2 ระดับได้ โดยคุณสามารถรอฟังเฉพาะเหตุการณ์การสร้าง การอัปเดต หรือการลบ หรือจะรอฟังการเปลี่ยนแปลงทุกประเภทในเส้นทางก็ได้ Cloud Functions รองรับตัวแฮนเดิลเหตุการณ์ต่อไปนี้สําหรับ Realtime Database
onWrite()
ซึ่งจะทริกเกอร์เมื่อสร้าง อัปเดต หรือลบข้อมูลใน Realtime DatabaseonCreate()
ซึ่งจะทริกเกอร์เมื่อมีการสร้างข้อมูลใหม่ใน Realtime DatabaseonUpdate()
ซึ่งจะทริกเกอร์เมื่อมีการอัปเดตข้อมูลใน Realtime DatabaseonDelete()
ซึ่งจะทริกเกอร์เมื่อมีการลบข้อมูลจาก 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
ระบบจะจับคู่เหตุการณ์ที่ตำแหน่งทั้ง 2 ตำแหน่งนี้
/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}"
2 ครั้ง: 1 ครั้งด้วย "hello": "world"
และอีกครั้งกับ "firebase": "functions"
จัดการข้อมูลเหตุการณ์
เมื่อจัดการเหตุการณ์ Realtime Database ออบเจ็กต์ข้อมูลที่แสดงผลคือ DataSnapshot
สําหรับเหตุการณ์ onWrite
หรือ onUpdate
พารามิเตอร์แรกคือออบเจ็กต์ Change
ที่มีภาพรวม 2 รายการซึ่งแสดงสถานะข้อมูลก่อนและหลังเหตุการณ์เรียกให้แสดง สำหรับ 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);
});