تسريع instagram.com. الجزء 3

ننشر اليوم ترجمة للجزء الثالث من سلسلة من المواد حول تسريع instagram.com. في الجزء الأول ، تحدثنا عن تحميل البيانات مسبقًا ، في الجزء الثاني ، حول إرسال البيانات إلى العميل بمبادرة من الخادم. هذا عن التخزين المؤقت.



يبدأ العمل مع ذاكرة التخزين المؤقت


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

نحن نستخدم Redux لإدارة حالة instagram.com. نتيجة لذلك ، تبدو خطة التنفيذ الشاملة للمخطط أعلاه هكذا. نقوم بتخزين مجموعة فرعية من مستودع Redux على العميل ، في جدول DB المفهرس ، لتعبئة هذا المخزون في المرة الأولى التي يتم فيها تحميل الصفحة. ومع ذلك ، فإن العمل مع indexedDB ، وتنزيل البيانات من الخادم ، وتفاعل المستخدم مع الصفحة هي عمليات غير متزامنة. نتيجة لذلك ، قد نواجه مشاكل. إنها تتألف من حقيقة أن المستخدم يعمل مع الحالة المخبأة القديمة ، ونحن بحاجة إلى جعل إجراءات المستخدم تنطبق على الحالة الجديدة عند تلقيها من الخادم.

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


حالة العرق التي تحدث عندما يتفاعل المستخدم مع البيانات المخزنة مؤقتًا (يتم تمييز إجراءات Redux باللون الأخضر ، الحالة رمادية)

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

هذه الفكرة تقودنا إلى بنية النظام التالية:

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


حل مشكلة ناتجة عن حالة سباق باستخدام حالة وسيطة (يتم تمييز إجراءات Redux باللون الأخضر ، والحالة رمادية)

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

API


تتكون واجهة برمجة التطبيقات للحالة الوسيطة من وظيفتين رئيسيتين. هذا هو stagingAction stagingCommit :

 function stagingAction(    key: string,    promise: Promise<Action>, ): AsyncAction<State, Action> function stagingCommit(key: string): AsyncAction<State, Action> 

هناك العديد من الوظائف الأخرى ، على سبيل المثال ، لإلغاء التغييرات ومعالجة الحالات الحدودية ، لكننا لن نفكر فيها هنا.

تقبل وظيفة stagingAction الوعد الذي يحل لحدث يجب إرساله إلى حالة وسيطة. هذه الوظيفة تهيئة حالة وسيطة ومراقبة الإجراءات التي تم إرسالها منذ التهيئة. إذا قارنا ذلك مع أنظمة التحكم في الإصدار ، فقد اتضح أننا نتعامل مع إنشاء فرع محلي. سيتم وضع الإجراءات المستمرة في قائمة الانتظار وتطبيقها على الحالة المؤقتة بعد وصول بيانات جديدة.

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

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

 function fetchAndStageFeed() {    return stagingAction(        'feed',        (async () => {            const {data} = await fetchFeedTimeline();            return {                type: FEED_LOADED,                ...data,            };        })(),    ); } //          store.dispatch(fetchAndStageFeed()); //   ,    stagingCommit, //      'feed' //      store.dispatch(stagingCommit('feed')); 

أدى استخدام طريقة العرض للتغذية والقصص ، والتي تظهر فيها ذاكرة التخزين المؤقت إلى الواجهة ، إلى زيادة إنتاج المواد بنسبة 2.5٪ و 11٪ على التوالي. هذا ، بالإضافة إلى ذلك ، ساهم في حقيقة أنه ، في نظر المستخدمين ، اقترب إصدار الويب من النظام من عملاء Instagram لنظامي التشغيل iOS و Android.

أعزائي القراء! هل تستخدم أي أساليب لتحسين التخزين المؤقت عند العمل في مشاريعك؟


Source: https://habr.com/ru/post/ar472336/


All Articles