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

(אופציונלי) אב טיפוס ובדיקה באמצעות חבילת אמולטור מקומית של Firebase

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

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

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

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

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

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

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

אינטרנט v8

var database = firebase.database();

אינטרנט v9

import { getDatabase } from "firebase/database";

const database = getDatabase();

כתוב נתונים

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

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

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

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

אינטרנט v8

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

אינטרנט v9

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
  });
}

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

קרא נתונים

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

כדי לקרוא נתונים על נתיב ולהקשיב לשינויים, השתמש on() או once() שיטות של firebase.database.Reference להתבונן באירועים.

מִקרֶה שימוש אופייני
value קרא והאזין לשינויים בתוכן השביל כולו.

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

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

אינטרנט v8

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

אינטרנט v9

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);
});

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

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

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

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

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

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

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

אינטרנט v8

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);
});

אינטרנט v9

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);
});

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

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

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

אינטרנט v8

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

אינטרנט v9

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
});

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

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

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

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

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

אינטרנט v8

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);
}

אינטרנט v9

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);
}

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

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

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

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

אינטרנט v8

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

אינטרנט v9

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...
});

מחק נתונים

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

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

קבלת Promise

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

נתק את המאזינים

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

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

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

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

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

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

אינטרנט v8

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;
  });
}

אינטרנט v9

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;
  });
}

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

תוספות בצד השרת האטומיות

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

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 לאחר מכן מסנכרן את הנתונים עם שרתי מסדי הנתונים המרוחקים ועם לקוחות אחרים על בסיס "המאמץ הטוב ביותר".

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

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

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

הצעדים הבאים