קרא וכתוב נתונים באינטרנט

(אופציונלי) אב-טיפוס ובדיקה עם Firebase Local Emulator Suite

לפני שנדבר על האופן שבו האפליקציה שלך קוראת וכותבת למסד נתונים בזמן אמת, הבה נציג קבוצה של כלים שבהם אתה יכול להשתמש כדי לבחון את הפונקציונליות של מסד הנתונים בזמן אמת: Firebase Local Emulator Suite. אם אתה מנסה מודלים שונים של נתונים, מייעל את כללי האבטחה שלך, או עובד כדי למצוא את הדרך המשתלמת ביותר לאינטראקציה עם הקצה האחורי, היכולת לעבוד מקומית מבלי לפרוס שירותים חיים יכולה להיות רעיון מצוין.

אמולטור של מסד נתונים בזמן אמת הוא חלק מחבילת האמולטור המקומית, המאפשרת לאפליקציה שלך לקיים אינטראקציה עם תוכן מסד הנתונים ותצורת הדמיית שלך, כמו גם עם משאבי הפרויקט המחויכים שלך (פונקציות, מסדי נתונים אחרים וכללי אבטחה).

השימוש באמולטור Realtime Database כולל רק כמה שלבים:

  1. הוספת שורת קוד לתצורת הבדיקה של האפליקציה שלך כדי להתחבר לאמולטור.
  2. מן השורש של ספריית הפרויקט המקומית, פועל firebase emulators:start .
  3. ביצוע שיחות מקוד אב הטיפוס של האפליקציה שלך באמצעות SDK של פלטפורמת Realtime Database כרגיל, או באמצעות Realtime Database REST API.

מפורטת בהדרכה המעורבת מסד זמן אמת ותפקידי ענן נגישה. כמו כן כדאי להעיף מבט לעבר הקדמת Suite Emulator המקומית .

קבל הפניה למסד נתונים

כדי לקרוא או לכתוב נתונים מבסיס הנתונים, אתה צריך מופע של firebase.database.Reference :

גרסת אינטרנט 9

import { getDatabase } from "firebase/database";

const database = getDatabase();

גרסת אינטרנט 8

var database = firebase.database();

כתוב נתונים

מסמך זה מכסה את היסודות של אחזור נתונים וכיצד להזמין ולסנן נתוני Firebase.

נתוני Firebase מאוחזר על ידי צירוף של מאזין אסינכרוני על firebase.database.Reference . המאזין מופעל פעם אחת עבור המצב ההתחלתי של הנתונים ושוב בכל פעם שהנתונים משתנים.

פעולות כתיבה בסיסיות

עבור פעולות כתיבה בסיסיות, אתה יכול להשתמש set() כדי לשמור את נתון הפניה שצוינה, החלפה כול נתון קיימים על השביל. לדוגמא יישום בלוגים חברתי עשוי להוסיף משתמש עם set() כדלקמן:

גרסת אינטרנט 9

import { getDatabase, ref, set } from "firebase/database";

function writeUserData(userId, name, email, imageUrl) {
  const db = getDatabase();
  set(ref(db, 'users/' + userId), {
    username: name,
    email: email,
    profile_picture : imageUrl
  });
}

גרסת אינטרנט 8

function writeUserData(userId, name, email, imageUrl) {
  firebase.database().ref('users/' + userId).set({
    username: name,
    email: email,
    profile_picture : imageUrl
  });
}

באמצעות set() דורסת הנתונים במיקום שצוין, לרבות כל הצמתים הילד.

קרא נתונים

הקשיבו לאירועים ערכיים

כדי לקרוא נתונים על נתיב ולהקשיב לשינויים, להשתמש onValue() כדי להתבונן באירועים. אתה יכול להשתמש באירוע זה כדי לקרוא תמונות סטטיות של התוכן בנתיב נתון, כפי שהם היו קיימים בזמן האירוע. שיטה זו מופעלת פעם אחת כאשר המאזין מחובר ושוב בכל פעם שהנתונים, כולל ילדים, משתנים. ההתקשרות חזרה לאירוע מועברת תמונת מצב המכילה את כל הנתונים באותו מיקום, כולל נתוני ילדים. אם אין נתונים, תמונת המצב תחזור false כאשר אתה קורא exists() ו null כאשר אתה קורא val() על זה.

הדוגמה הבאה מדגימה אפליקציית בלוגים חברתית המאחזרת את ספירת הכוכבים של פוסט ממסד הנתונים:

גרסת אינטרנט 9

import { getDatabase, ref, onValue} from "firebase/database";

const db = getDatabase();
const starCountRef = ref(db, 'posts/' + postId + '/starCount');
onValue(starCountRef, (snapshot) => {
  const data = snapshot.val();
  updateStarCount(postElement, data);
});

גרסת אינטרנט 8

var starCountRef = firebase.database().ref('posts/' + postId + '/starCount');
starCountRef.on('value', (snapshot) => {
  const data = snapshot.val();
  updateStarCount(postElement, data);
});

המאזין מקבל snapshot המכיל את הנתונים במיקום שצוין באתר בעת האירוע. ניתן לאחזר את הנתונים snapshot עם val() שיטה.

קרא נתונים פעם אחת

קרא נתונים פעם אחת עם get()

ה-SDK נועד לנהל אינטראקציות עם שרתי מסד נתונים בין אם האפליקציה שלך מקוונת או לא מקוונת.

בדרך כלל, עליך להשתמש בטכניקות אירועי ערך המתוארות לעיל כדי לקרוא נתונים כדי לקבל הודעה על עדכונים לנתונים מה-backend. טכניקות ההאזנה מפחיתות את השימוש והחיוב שלך, והן מותאמות כדי להעניק למשתמשים שלך את החוויה הטובה ביותר כשהם עוברים לאינטרנט ולא מקוון.

אם אתה צריך את הנתונים רק פעם אחת, אתה יכול להשתמש get() כדי לקבל תמונת מצב של נתונים מבסיס הנתונים. אם מסיבה כלשהי get() אינו מסוגל להחזיר את ערך השרת, לקוח יחטט מטמון האחסון המקומי ולחזור שגיאה אם הערך עדיין לא נמצא.

שימוש מיותר של get() יכול להגדיל את השימוש ברוחב הפס להוביל לאובדן של ביצועים, אשר ניתן למנוע באמצעות מאזין בזמן אמת כפי שפורט לעיל.

גרסת אינטרנט 9

import { getDatabase, ref, child, get } from "firebase/database";

const dbRef = ref(getDatabase());
get(child(dbRef, `users/${userId}`)).then((snapshot) => {
  if (snapshot.exists()) {
    console.log(snapshot.val());
  } else {
    console.log("No data available");
  }
}).catch((error) => {
  console.error(error);
});

גרסת אינטרנט 8

const dbRef = firebase.database().ref();
dbRef.child("users").child(userId).get().then((snapshot) => {
  if (snapshot.exists()) {
    console.log(snapshot.val());
  } else {
    console.log("No data available");
  }
}).catch((error) => {
  console.error(error);
});

קרא נתונים פעם אחת עם צופה

במקרים מסוימים ייתכן שתרצה שהערך מהמטמון המקומי יוחזר באופן מיידי, במקום לבדוק אם יש ערך מעודכן בשרת. במקרים אלו ניתן להשתמש once() כדי לקבל את הנתונים מהמטמון לדיסק המקומי מיד.

זה שימושי עבור נתונים שצריך לטעון רק פעם אחת ואינם צפויים להשתנות לעתים קרובות או לדרוש האזנה פעילה. לדוגמה, אפליקציית הבלוגים בדוגמאות הקודמות משתמשת בשיטה זו כדי לטעון פרופיל של משתמש כאשר הוא מתחיל לכתוב פוסט חדש:

גרסת אינטרנט 9

import { getDatabase, ref, onValue } from "firebase/database";
import { getAuth } from "firebase/auth";

const db = getDatabase();
const auth = getAuth();

const userId = auth.currentUser.uid;
return onValue(ref(db, '/users/' + userId), (snapshot) => {
  const username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
  // ...
}, {
  onlyOnce: true
});

גרסת אינטרנט 8

var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).once('value').then((snapshot) => {
  var username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
  // ...
});

עדכון או מחיקת נתונים

עדכן שדות ספציפיים

כדי לכתוב בו זמנית לילדים ספציפיים של צומת מבלי להחליף צומת ילד אחרים, להשתמש update() השיטה.

בעת התקשרות update() , אתה יכול לעדכן ערכי ילד ברמה נמוכה יותר על ידי ציון נתיב עבור המפתח. אם הנתונים מאוחסנים במקומות מרובים סולם טוב יותר, אתה יכול לעדכן את כל המופעים של נתונים באמצעות מאוורר-אאוט נתונים .

לדוגמה, אפליקציית בלוגים חברתית עשויה ליצור פוסט ולעדכן אותו בו-זמנית לעדכון הפעילות האחרונה ולפיד הפעילות של המשתמש המפרסם באמצעות קוד כזה:

גרסת אינטרנט 9

function writeNewPost(uid, username, picture, title, body) {
  const db = getDatabase();

  // A post entry.
  const postData = {
    author: username,
    uid: uid,
    body: body,
    title: title,
    starCount: 0,
    authorPic: picture
  };

  // Get a key for a new Post.
  const newPostKey = push(child(ref(db), 'posts')).key;

  // Write the new post's data simultaneously in the posts list and the user's post list.
  const updates = {};
  updates['/posts/' + newPostKey] = postData;
  updates['/user-posts/' + uid + '/' + newPostKey] = postData;

  return update(ref(db), updates);
}

גרסת אינטרנט 8

function writeNewPost(uid, username, picture, title, body) {
  // A post entry.
  var postData = {
    author: username,
    uid: uid,
    body: body,
    title: title,
    starCount: 0,
    authorPic: picture
  };

  // Get a key for a new Post.
  var newPostKey = firebase.database().ref().child('posts').push().key;

  // Write the new post's data simultaneously in the posts list and the user's post list.
  var updates = {};
  updates['/posts/' + newPostKey] = postData;
  updates['/user-posts/' + uid + '/' + newPostKey] = postData;

  return firebase.database().ref().update(updates);
}

שימושים דוגמה זו push() כדי ליצור פוסט ב הצומת המכיל הודעות לכל המשתמשים בדומיין /posts/$postid ובמקביל לאחזר את המפתח. המפתח לאחר מכן ניתן להשתמש כדי ליצור ערך שני הודעות של המשתמש ב /user-posts/$userid/$postid .

באמצעות נתיבים אלה, אתה יכול לבצע עדכונים סימולטני ליעדים רבים בעץ JSON עם שיחה אחת כדי update() , כגון איך בדוגמה זו יוצרת את הפוסט החדש בשני המקומות. עדכונים בו-זמניים שנעשו בדרך זו הם אטומיים: או שכל העדכונים מצליחים או שכל העדכונים נכשלים.

הוסף התקשרות חוזרת של השלמה

אם אתה רוצה לדעת מתי הנתונים שלך הועברו, אתה יכול להוסיף התקשרות חזרה. שניהם set() ו update() לקחת התקשרות השלמת אופציונלי נקרא כאשר הכתיבה כבר שבוצעו בבסיס הנתונים. אם השיחה לא הצליחה, ההתקשרות חזרה מועברת אובייקט שגיאה המציין מדוע התרחש הכשל.

גרסת אינטרנט 9

import { getDatabase, ref, set } from "firebase/database";

const db = getDatabase();
set(ref(db, 'users/' + userId), {
  username: name,
  email: email,
  profile_picture : imageUrl
})
.then(() => {
  // Data saved successfully!
})
.catch((error) => {
  // The write failed...
});

גרסת אינטרנט 8

firebase.database().ref('users/' + userId).set({
  username: name,
  email: email,
  profile_picture : imageUrl
}, (error) => {
  if (error) {
    // The write failed...
  } else {
    // Data saved successfully!
  }
});

מחק נתונים

הדרך הפשוטה ביותר נתונים המחיקה היא להתקשר remove() על הפניה למיקום של הנתונים.

אתה גם יכול למחוק ידי ציון null כערך לעוד פעולת הכתיבה כגון set() או update() . אתה יכול להשתמש בטכניקה זו עם update() כדי למחוק ילדים מרובים בשיחת API יחידה.

קבלת Promise

כדי לדעת מתי הנתונים שלך מחויבת לשרת מסד Firebase זמן אמת, אתה יכול להשתמש Promise . שניהם set() ו update() יכולה להחזיר Promise אתה יכול להשתמש בו כדי לדעת מתי כתיבה מחויבת למסד הנתונים.

לנתק מאזינים

התקשרויות חוזרות יוסרו על ידי קריאה off() שיטה על הפנייה למאגר הנתונים Firebase שלך.

אתה יכול להסיר מאזין אחד על ידי העברתו כפרמטר off() . קורא off() על מיקום ללא ויכוחים מסיר את כל המאזינים במיקום זה.

קורא off() על מאזין ההורה אינו מסיר אוטומטית המאזינים רשום על בלוטות הילד שלה; off() חייב גם להיקרא על כול מאזיני ילד להסיר את ההתקשרות.

שמור נתונים כעסקאות

כאשר עובד עם נתונים שעלולים להיות פגום על ידי שינויים מקבילים, כגון מונים מצטברים, אתה יכול להשתמש במבצע עסקה . אתה יכול לתת לפעולה זו פונקציית עדכון והתקשרות אופציונלית להשלמה. פונקציית העדכון לוקחת את המצב הנוכחי של הנתונים כארגומנט ומחזירה את המצב הרצוי החדש שתרצה לכתוב. אם לקוח אחר כותב למיקום לפני שהערך החדש שלך נכתב בהצלחה, פונקציית העדכון שלך נקראת שוב עם הערך הנוכחי החדש, והכתיבה מתבצעת מחדש.

לדוגמה, באפליקציית הבלוגים החברתיים לדוגמה, תוכל לאפשר למשתמשים לסמן ולבטל כוכב בפוסטים ולעקוב אחר כמה כוכבים פוסט קיבל באופן הבא:

גרסת אינטרנט 9

import { getDatabase, ref, runTransaction } from "firebase/database";

function toggleStar(uid) {
  const db = getDatabase();
  const postRef = ref(db, '/posts/foo-bar-123');

  runTransaction(postRef, (post) => {
    if (post) {
      if (post.stars && post.stars[uid]) {
        post.starCount--;
        post.stars[uid] = null;
      } else {
        post.starCount++;
        if (!post.stars) {
          post.stars = {};
        }
        post.stars[uid] = true;
      }
    }
    return post;
  });
}

גרסת אינטרנט 8

function toggleStar(postRef, uid) {
  postRef.transaction((post) => {
    if (post) {
      if (post.stars && post.stars[uid]) {
        post.starCount--;
        post.stars[uid] = null;
      } else {
        post.starCount++;
        if (!post.stars) {
          post.stars = {};
        }
        post.stars[uid] = true;
      }
    }
    return post;
  });
}

שימוש בעסקה מונע מספירת כוכבים להיות שגויה אם מספר משתמשים מככבים באותו פוסט בו-זמנית או שללקוח היו נתונים מיושנים. אם העסקה נדחתה, השרת מחזיר את הערך הנוכחי ללקוח, אשר מריץ את העסקה שוב עם הערך המעודכן. זה חוזר על עצמו עד שהעסקה תתקבל או שתבטל את העסקה.

מרווחים בצד השרת האטומי

במקרה השימוש שלמעלה אנו כותבים שני ערכים למסד הנתונים: מזהה המשתמש שמככב/מבטל את הכוכב בפוסט, וספירת הכוכבים המוגדלת. אם אנחנו כבר יודעים שהמשתמש מסמן את הפוסט בכוכב, נוכל להשתמש בפעולת תוספת אטומית במקום בטרנזקציה.

function addStar(uid, key) {
  const updates = {};
  updates[`posts/${key}/stars/${uid}`] = true;
  updates[`posts/${key}/starCount`] = firebase.database.ServerValue.increment(1);
  updates[`user-posts/${key}/stars/${uid}`] = true;
  updates[`user-posts/${key}/starCount`] = firebase.database.ServerValue.increment(1);
  firebase.database().ref().update(updates);
}

קוד זה אינו משתמש בפעולת עסקה, כך שהוא אינו מופעל מחדש באופן אוטומטי אם יש עדכון מתנגש. עם זאת, מכיוון שפעולת ההגדלה מתרחשת ישירות על שרת מסד הנתונים, אין סיכוי להתנגשות.

אם ברצונך לזהות ולדחות התנגשויות ספציפיות ליישום, כגון משתמש שמככב פוסט שכבר סימן בכוכב לפני כן, עליך לכתוב כללי אבטחה מותאמים אישית עבור מקרה השימוש הזה.

עבודה עם נתונים במצב לא מקוון

אם לקוח מאבד את חיבור הרשת שלו, האפליקציה שלך תמשיך לפעול כהלכה.

כל לקוח המחובר למסד נתונים של Firebase שומר על גרסה פנימית משלו של כל נתונים פעילים. כאשר נתונים נכתבים, הם נכתבים תחילה לגרסה המקומית הזו. לאחר מכן, לקוח Firebase מסנכרן את הנתונים האלה עם שרתי מסד הנתונים המרוחקים ועם לקוחות אחרים על בסיס "המאמץ הטוב ביותר".

כתוצאה מכך, כל הכתיבה למסד הנתונים מפעילה אירועים מקומיים באופן מיידי, לפני כל כתיבה של נתונים לשרת. המשמעות היא שהאפליקציה שלך נשארת מגיבה ללא קשר לאחזור הרשת או הקישוריות.

ברגע שהקישוריות מתבססת מחדש, האפליקציה שלך מקבלת את קבוצת האירועים המתאימה כך שהלקוח מסתנכרן עם מצב השרת הנוכחי, ללא צורך לכתוב שום קוד מותאם אישית.

נידבר יותר על התנהגות לא מקוונת למידע נוסף על מקוון ויכולות מחוברות ..

הצעדים הבאים