قراءة وكتابة البيانات على الويب

(اختياري) النموذج الأولي والاختبار باستخدام Firebase Local Emulator Suite

قبل التحدث عن كيفية قراءة تطبيقك من قاعدة بيانات Realtime والكتابة إليها ، دعنا نقدم مجموعة من الأدوات التي يمكنك استخدامها لتصميم واختبار وظيفة Realtime Database: Firebase Local Emulator Suite. إذا كنت تجرب نماذج بيانات مختلفة ، أو تقوم بتحسين قواعد الأمان الخاصة بك ، أو تعمل على إيجاد الطريقة الأكثر فعالية من حيث التكلفة للتفاعل مع النهاية الخلفية ، فإن القدرة على العمل محليًا دون نشر الخدمات المباشرة يمكن أن تكون فكرة رائعة.

يعد محاكي Realtime Database جزءًا من Local Emulator Suite ، والذي يمكّن تطبيقك من التفاعل مع محتوى قاعدة البيانات التي تمت محاكاتها وتكوينها ، بالإضافة إلى موارد المشروع التي تمت محاكاتها اختياريًا (الوظائف وقواعد البيانات الأخرى وقواعد الأمان).

يتضمن استخدام محاكي Realtime Database بضع خطوات فقط:

  1. إضافة سطر من التعليمات البرمجية إلى التكوين التجريبي لتطبيقك للاتصال بالمحاكي.
  2. من جذر دليل المشروع الخاص المحلي، وتشغيل firebase emulators:start .
  3. إجراء مكالمات من رمز النموذج الأولي للتطبيق باستخدام SDK للنظام الأساسي لقاعدة البيانات Realtime كالمعتاد ، أو باستخدام Realtime Database REST API.

A مفصل تجول تشمل قاعدة البيانات في الوقت الحقيقي وظائف السحب متاح. يجب أيضا أن يكون لها نظرة على المحاكي جناح المحلية مقدمة .

احصل على مرجع قاعدة البيانات

لقراءة أو كتابة البيانات من قاعدة البيانات، تحتاج مثيل 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() الكتابة فوق البيانات في الموقع المحدد، بما في ذلك أي العقد التابعة.

إقرأ البيانات

استمع إلى الأحداث القيمة

لقراءة البيانات في مسار والاستماع للتغييرات، استخدم on() أو once() طرق firebase.database.Reference لمراقبة الأحداث.

حدث استخدام نموذجي
value اقرأ واستمع إلى التغييرات التي تم إجراؤها على محتويات المسار بالكامل.

يمكنك استخدام value الحدث لقراءة لقطة ثابتة من محتويات في مسار معين، لأنها كانت موجودة في وقت وقوع الحدث. يتم تشغيل هذه الطريقة مرة واحدة عند إرفاق المستمع ومرة ​​أخرى في كل مرة تتغير فيها البيانات ، بما في ذلك الأطفال. يتم تمرير رد اتصال الحدث على لقطة تحتوي على جميع البيانات الموجودة في ذلك الموقع ، بما في ذلك البيانات التابعة. إذا كان هناك أية بيانات، فإن لقطة عودة 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 لإدارة التفاعلات مع خوادم قاعدة البيانات سواء كان تطبيقك متصلاً بالإنترنت أو غير متصل بالإنترنت.

بشكل عام ، يجب عليك استخدام تقنيات أحداث القيمة الموضحة أعلاه لقراءة البيانات للحصول على إشعار بتحديثات البيانات من الواجهة الخلفية. تعمل تقنيات المستمع على تقليل الاستخدام والفوترة ، وهي مُحسَّنة لمنح المستخدمين أفضل تجربة أثناء اتصالهم بالإنترنت أو عدم الاتصال بالإنترنت.

إذا كنت في حاجة إلى البيانات مرة واحدة فقط، يمكنك استخدام 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 بعد ذلك بمزامنة تلك البيانات مع خوادم قاعدة البيانات البعيدة ومع العملاء الآخرين على أساس "أفضل جهد".

نتيجة لذلك ، تقوم جميع عمليات الكتابة في قاعدة البيانات بتشغيل الأحداث المحلية على الفور ، قبل كتابة أي بيانات إلى الخادم. هذا يعني أن تطبيقك يظل مستجيبًا بغض النظر عن زمن انتقال الشبكة أو الاتصال.

بمجرد إعادة إنشاء الاتصال ، يتلقى تطبيقك مجموعة الأحداث المناسبة بحيث يتزامن العميل مع حالة الخادم الحالية ، دون الحاجة إلى كتابة أي رمز مخصص.

سوف نتحدث أكثر عن سلوك حاليا في تعلم المزيد حول الانترنت وقدرات متواجد حاليا ..

الخطوات التالية