اختار المؤلف /dev/color لتلقي تبرع كجزء من برنامج الكتابة من أجل التبرعات.
مقدمة
تعتمد معظم التطبيقات على البيانات، سواء كانت من قاعدة بيانات أو واجهة برمجة تطبيقات. يرسل استرداد البيانات من واجهة برمجة التطبيقات طلب شبكة إلى خادم واجهة برمجة التطبيقات ويعيد البيانات كاستجابة. تستغرق هذه الرحلات الدورية وقتًا ويمكن أن تزيد من وقت الاستجابة للتطبيق للمستخدمين. علاوة على ذلك، تقيد معظم واجهات برمجة التطبيقات بعدد الطلبات التي يمكنها خدمة التطبيق داخل إطار زمني محدد، وهو عملية تعرف بـ تقييد المعدل.
للتغلب على هذه المشاكل، يمكنك تخزين بياناتك في ذاكرة التخزين المؤقت بحيث يقوم التطبيق بعملية طلب واحدة إلى واجهة برمجة التطبيقات، وستسترد الطلبات البيانات فيما بعد من الذاكرة المؤقتة. Redis، قاعدة بيانات في الذاكرة تخزن البيانات في ذاكرة الخادم، هي أداة شائعة لتخزين البيانات. يمكنك الاتصال بـ Redis في Node.js باستخدام الوحدة النمطية node-redis
، والتي تمنحك طرقًا لاسترداد وتخزين البيانات في Redis.
في هذا البرنامج التعليمي، ستقوم ببناء تطبيق Express الذي يسترد البيانات من واجهة برمجة التطبيقات RESTful باستخدام وحدة الـaxios
. بعد ذلك، ستقوم بتعديل التطبيق لتخزين البيانات المُحمَلة من الواجهة البرمجية في Redis باستخدام وحدة node-redis
. بعد ذلك، ستقوم بتنفيذ فترة صلاحية الذاكرة المؤقتة بحيث يمكن للذاكرة المؤقتة أن تنتهي بعد مرور فترة زمنية معينة. وأخيرًا، ستستخدم وسيط Express لتخزين البيانات في الذاكرة المؤقتة.
المتطلبات المسبقة
لمتابعة البرنامج التعليمي، ستحتاج إلى:
-
إعداد بيئة Node.js على الخادم الخاص بك. إذا كنت تستخدم Ubuntu 22.04، قم بتثبيت آخر إصدار من Node.js و npm عن طريق اتباع الخيار 3 في كيفية تثبيت Node.js على Ubuntu 22.04. بالنسبة لأنظمة التشغيل الأخرى، انظر سلسلة كيفية تثبيت Node.js وإنشاء بيئة تطوير محلية.
-
تم تثبيت Redis على خادمك. إذا كنت تستخدم Ubuntu 22.04، اتبع الخطوات 1 و 2 في كيفية تثبيت وتأمين Redis على Ubuntu 22.04. إذا كنت تعمل على نظام تشغيل آخر، انظر كيفية تثبيت وتأمين Redis.
-
معرفة البرمجة الغير متزامنة. تابع فهم حلقة الحدث، والاستدعاءات الرجعية، والوعود، وAsync/Await في JavaScript.
-
المعرفة الأساسية في استخدام إطار الويب Express. انظر كيفية البدء مع Node.js و Express.
الخطوة 1 — إعداد المشروع
في هذه الخطوة، ستقوم بتثبيت التبعيات الضرورية لهذا المشروع وبدء خادم Express. في هذا البرنامج التعليمي، ستقوم بإنشاء ويكي يحتوي على معلومات حول أنواع مختلفة من الأسماك. سنطلق على المشروع اسم fish_wiki
.
أولاً، قم بإنشاء الدليل للمشروع باستخدام أمر mkdir
:
انتقل إلى الدليل:
تهيئة ملف package.json
باستخدام أمر npm
:
الخيار -y
يقبل جميع القيم الافتراضية تلقائيًا.
عند تشغيل أمر npm init
، سيقوم بإنشاء ملف package.json
في الدليل الخاص بك بالمحتويات التالية:
OutputWrote to /home/your_username/<^>fish_wiki<^/package.json:
{
"name": "fish_wiki",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
بعد ذلك، ستقوم بتثبيت الحزم التالية:
express
: إطار عمل لخادم الويب لـ Node.js.axios
: عميل HTTP لـ Node.js، والذي يفيد في إجراءات استدعاء الواجهة البرمجية للتطبيقات.node-redis
: عميل Redis الذي يتيح لك تخزين البيانات والوصول إليها في Redis.
لتثبيت الحزم الثلاث معًا، أدخل الأمر التالي:
بعد تثبيت الحزم، ستقوم بإنشاء خادم Express أساسي.
باستخدام nano
أو محرر النص الذي تفضله، أنشئ وافتح ملف server.js
:
في ملف server.js
الخاص بك، أدخل الكود التالي لإنشاء خادم Express:
أولاً، استورد express
في الملف. في السطر الثاني، قم بتعيين المتغير app
كنسخة من express
، مما يمنحك الوصول إلى الوسائل مثل get
، post
، listen
، والمزيد. سيتمركز هذا البرنامج التعليمي على الوسائل get
و listen
.
في السطر التالي، قم بتعريف المتغير port
وتعيينه لرقم المنفذ الذي تريد أن يستمع إليه الخادم. إذا لم يتوفر رقم منفذ في ملف المتغيرات البيئية، فسيتم استخدام المنفذ 3000
كافتراضي.
أخيرًا ، باستخدام المتغير app
، قم باستدعاء طريقة listen()
لوحدة البرنامج express
لبدء الخادم على المنفذ 3000
.
احفظ وأغلق الملف.
شغل ملف server.js
باستخدام أمر node
لبدء الخادم:
سيتم تسجيل رسالة مماثلة للتالية في وحدة التحكم:
OutputApp listening on port 3000
الإخراج يؤكد أن الخادم يعمل وجاهز لخدمة أي طلبات على المنفذ 3000
. نظرًا لأن Node.js لا يعيد تحميل الخادم تلقائيًا عند تغيير الملفات ، ستقوم الآن بإيقاف الخادم باستخدام CTRL+C
حتى تتمكن من تحديث server.js
في الخطوة التالية.
بمجرد تثبيت الاعتماديات وإنشاء خادم Express ، ستسترد البيانات من واجهة برمجة التطبيقات (API) RESTful.
الخطوة 2 — استرداد البيانات من واجهة برمجة التطبيقات (API) RESTful دون تخزين مؤقت
في هذه الخطوة ، ستبني على الخادم Express من الخطوة السابقة لاسترداد البيانات من واجهة برمجة التطبيقات (API) RESTful دون تنفيذ تخزين مؤقت ، مما يوضح ما يحدث عندما لا تتم تخزين البيانات في ذاكرة التخزين المؤقت.
للبدء ، افتح ملف server.js
في محرر النص الخاص بك:
بعد ذلك ، ستقوم باسترداد البيانات من واجهة برمجة التطبيقات (API) FishWatch. توفر واجهة برمجة التطبيقات (API) FishWatch معلومات حول أنواع الأسماك.
في ملف server.js
، قم بتعريف دالة تُطلب بيانات واجهة برمجة التطبيقات باستخدام الكود المميز التالي:
في السطر الثاني، قم بإستيراد وحدة axios
. بعد ذلك، قم بتعريف دالة غير متزامنة fetchApiData()
، التي تأخذ species
كمعلمة. لجعل الدالة غير متزامنة، ضع الكلمة المفتاحية async
قبلها.
ضمن الدالة، قم باستدعاء طريقة get()
من وحدة axios
باستخدام عنوان واجهة برمجة التطبيقات التي تريد أن تقوم الطريقة بجلب البيانات منها، وهو واجهة برمجة التطبيقات FishWatch في هذا المثال. بما أن طريقة get()
تنفذ وعدًا promise، ضع الكلمة المفتاحية await
لحل الوعد. بمجرد حل الوعد وإرجاع البيانات من واجهة برمجة التطبيقات، قم باستدعاء طريقة console.log()
. ستسجل طريقة console.log()
رسالة تقول إنه تم إرسال طلب إلى واجهة برمجة التطبيقات. أخيرًا، قم بإرجاع البيانات من واجهة برمجة التطبيقات.
بعد ذلك، ستقوم بتعريف مسار Express يقبل طلبات GET
. في ملف server.js
، قم بتعريف المسار بالكود التالي:
في الكود السابق، قم باستدعاء طريقة get()
من وحدة express
، التي تستمع فقط على طلبات GET
. تأخذ الطريقة معها معلمتين:
/fish/:species
: النقطة النهائية التي ستكون Express تستمع إليها. النقطة النهائية تأخذ معلمة مسار:species
التي تلتقط أي شيء يتم إدخاله في تلك الموضع في عنوان URL.getSpeciesData()
(لم يتم تعريفها بعد): وظيفة استدعاء ستتم استدعاؤها عندما يتطابق عنوان URL مع النقطة النهائية المحددة في الوسيطة الأولى.
الآن بعد تعريف المسار، حدد وظيفة استدعاء getSpeciesData
:
الدالة getSpeciesData
هي دالة معالجة غير متزامنة تمرر إلى الطريقة get()
في وحدة express
كوسيط ثانوي. تأخذ دالة getSpeciesData()
معها معلمتين: كائن الطلب (request) وكائن الاستجابة (response). كائن الطلب يحتوي على معلومات حول العميل، بينما يحتوي كائن الاستجابة على المعلومات التي سيتم إرسالها إلى العميل من Express.
بعد ذلك، أضف الكود المظلل لاستدعاء fetchApiData()
لاسترداد البيانات من واجهة برمجة التطبيقات في وظيفة استدعاء getSpeciesData()
:
في الدالة، تستخرج القيمة التي تم التقاطها من النقطة النهائية المخزنة في كائن req.params
، ثم تسند إلى المتغير species
. في السطر التالي، تعرف المتغير results
وتعيده إلى undefined
.
بعد ذلك، تقوم بإستدعاء الدالة fetchApiData()
مع المتغير species
كوسيط. إستدعاء دالة fetchApiData()
مسبوق ببنية await
لأنها تعيد وعدًا. عندما يتم حل الوعد، يُعيد البيانات التي تُسند بعدها إلى المتغير results
.
بعد ذلك، قم بإضافة الكود المظلل للتعامل مع أخطاء التشغيل:
تقوم بتعريف الكتلة try/catch
للتعامل مع أخطاء التشغيل. في الكتلة try
، تقوم بإستدعاء fetchApiData()
لاسترداد البيانات من واجهة برمجة التطبيقات.
إذا تم إكتشاف خطأ، تقوم الكتلة catch
بتسجيل الخطأ وإرجاع رمز الحالة 404
مع استجابة “البيانات غير متوفرة”.
معظم واجهات برمجة التطبيقات تعيد رمز الحالة 404 عندما لا تتوفر بيانات لاستعلام معين، مما يؤدي تلقائيًا إلى تنفيذ كتلة catch
. ومع ذلك، تعيد واجهة برمجة تطبيقات FishWatch رمز الحالة 200 مع مصفوفة فارغة عندما لا توجد بيانات لهذا الاستعلام المحدد. يعني رمز الحالة 200 أن الطلب ناجح، لذا لا يتم تشغيل كتلة catch()
أبدًا.
لتشغيل كتلة catch()
، تحتاج إلى التحقق مما إذا كانت المصفوفة فارغة ورمي خطأ عندما تُقيم الشرط if
بصحة. عندما تُقيم شروط if
بخطأ، يمكنك إرسال استجابة إلى العميل تحتوي على البيانات.
للقيام بذلك، أضف الكود المظلل:
بمجرد عودة البيانات من واجهة برمجة التطبيقات، يقوم البيانات if
بفحص متغير results
ما إذا كان فارغًا. إذا تم تحقيق الشرط، يتم استخدام البيانات throw
لرمي خطأ مخصص برسالة API returned an empty array
. بعد تشغيله، يتم تبديل التنفيذ إلى كتلة الامساك catch
، التي تسجل رسالة الخطأ وتعيد استجابة 404.
بالمقابل، إذا كان متغير results
يحتوي على بيانات، فلن يتم تحقيق شرط البيانات if
. نتيجة لذلك، سيتخطى البرنامج كتلة البيانات if
وينفذ طريقة send
لكائن الاستجابة، الذي يرسل استجابة إلى العميل.
تأخذ طريقة send
كائنًا يحتوي على الخصائص التالية:
-
fromCache
: تقبل الخاصية قيمة تساعدك في معرفة ما إذا كانت البيانات قادمة من ذاكرة التخزين المؤقت Redis أم من واجهة برمجة التطبيقات. لقد قمت الآن بتعيين قيمةfalse
لأن البيانات تأتي من واجهة برمجة التطبيقات. -
data
: يتم تعيين الخاصية المتغيرresults
الذي يحتوي على البيانات المعادة من واجهة برمجة التطبيقات.
في هذه النقطة، سيكون الكود الخاص بك كاملًا على النحو التالي:
الآن بعد أن تم وضع كل شيء في مكانه، قم بحفظ الملف والخروج.
ابدأ خادم express:
تقبل واجهة برمجة التطبيقات لرصد الأسماك العديد من الأنواع، ولكننا سنستخدم فقط نوع أسماك red-snapper
كمعلمة طريق على النقطة النهائية التي ستقوم باختبارها طوال هذا البرنامج التعليمي.
الآن، قم بتشغيل متصفح الويب المفضل لديك على جهاز الكمبيوتر المحلي الخاص بك. انتقل إلى عنوان URL التالي: http://localhost:3000/fish/red-snapper
.
ملاحظة: إذا كنت تتابع البرنامج التعليمي على خادم عن بعد، يمكنك عرض التطبيق في متصفحك باستخدام توجيه المنفذ.
مع تشغيل خادم Node.js لا يزال، افتح محطة أخرى في جهاز الكمبيوتر المحلي الخاص بك، ثم أدخل الأمر التالي:
عند الاتصال بالخادم، انتقل إلى عنوان http://localhost:3000/fish/red-snapper
على متصفح الويب الخاص بجهازك المحلي.
بمجرد تحميل الصفحة، يجب أن ترى fromCache
مضبوطة على false
.
الآن، قم بتحديث العنوان URL ثلاث مرات إضافية وانظر إلى المحطة الطرفية الخاصة بك. ستقوم المحطة بتسجيل “تم إرسال طلب إلى خادم الواجهة البرمجية” بقدر مرات تحديث متصفحك.
إذا قمت بتحديث العنوان URL ثلاث مرات بعد الزيارة الأولى، ستبدو النتيجة النهائية كما يلي:
Output
App listening on port 3000
Request sent to the API
Request sent to the API
Request sent to the API
Request sent to the API
تُظهر هذه النتيجة أن طلب الشبكة يتم إرساله إلى خادم واجهة برمجة التطبيقات في كل مرة تقوم فيها بتحديث المتصفح. إذا كان لديك تطبيق يستخدمه 1000 مستخدم يصلون إلى نفس النقطة النهائية، فهذا يعني أنه سيتم إرسال 1000 طلب شبكة إلى واجهة برمجة التطبيقات.
عند تنفيذ التخزين المؤقت، سيتم إجراء طلب إلى واجهة برمجة التطبيقات مرة واحدة فقط. جميع الطلبات التالية ستحصل على البيانات من الذاكرة المؤقتة، مما يعزز أداء تطبيقك.
للآن، قم بإيقاف خادم Express الخاص بك باستخدام CTRL+C
.
الآن بما أنه يمكنك طلب البيانات من واجهة برمجة تطبيقات (API) وتقديمها للمستخدمين، ستخزن البيانات التي تم استرجاعها من واجهة برمجة التطبيقات (API) في Redis.
الخطوة 3 — تخزين طلبات واجهة برمجة التطبيقات RESTful باستخدام Redis
في هذا القسم، ستقوم بتخزين البيانات من واجهة برمجة التطبيقات (API) بحيث يتم طلب البيانات من خادم API فقط في زيارة البداية إلى نقطة نهاية تطبيقك، وستقوم جميع الطلبات التالية بجلب البيانات من ذاكرة التخزين المؤقت Redis.
افتح ملف server.js
:
في ملف server.js
الخاص بك، استورد وحدة node-redis
:
في نفس الملف، قم بالاتصال بـ Redis باستخدام وحدة node-redis
عن طريق إضافة الكود المميز كما في الخطوات التالية:
أولاً، قم بتعريف متغير redisClient
وتعيين قيمته إلى undefined. بعد ذلك، قم بتعريف دالة غير مسماة تنفذ ذاتياً بطريقة غير متزامنة، وهي دالة تقوم بالتشغيل مباشرة بعد تعريفها. يمكنك تعريف دالة غير مسماة تنفذ ذاتياً عن طريق تقويم تعريف الدالة بدون اسم داخل قوسين (async () => {...})
. لجعلها تنفذ ذاتياً، اتبعها مباشرة بمجموعة أخرى من القوسين ()
، مما يظهر كـ (async () => {...})()
.
Dاطلب من داخل الدالة استدعاء طريقة createClient() في وحدة redis التي تنشئ كائن redis. نظرًا لعدم توفيرك للمنفذ الذي يجب على Redis استخدامه عند استدعاء طريقة createClient()، ستستخدم Redis المنفذ 6379، وهو المنفذ الافتراضي.
تستدعي أيضًا طريقة on() في Node.js التي تسجل الأحداث على كائن Redis. تأخذ طريقة on() معها معها معها وسيطتين: error واستدعاءً مرفوع. الوسيط الأول error هو الحدث الذي يتم تنشيطه عندما يواجه Redis خطأ. الوسيط الثاني هو استدعاء يعمل عندما يتم بث الحدث error. يقوم الاستدعاء بتسجيل الخطأ في وحدة التحكم.
أخيرًا، تستدعي طريقة connect()، التي تبدأ الاتصال بـ Redis على المنفذ الافتراضي 6379. تُرجع طريقة connect() وعدًا، لذلك تضيف البادئة await قبلها لحل الوعد.
الآن بمجرد أن تكون التطبيق متصلاً بـ Redis، ستقوم بتعديل استدعاء getSpeciesData() لتخزين البيانات في Redis في الزيارة الأولية واسترداد البيانات من الذاكرة المؤقتة لجميع الطلبات التالية.
في ملف server.js الخاص بك، أضف وقم بتحديث الشيفرة المشار إليها بالإضاءة:
في الدالة getSpeciesData
، تعرف المتغير isCached
بقيمة false
. ضمن كتلة try
، تقوم باستدعاء طريقة get()
لوحدة node-redis
باستخدام species
كوسيط. عندما تجد الطريقة المفتاح في Redis الذي يطابق قيمة المتغير species
، يتم إرجاع البيانات، التي يتم تعيينها بعد ذلك إلى المتغير cacheResults
.
بعد ذلك، يتحقق البيان if
مما إذا كان للمتغير cacheResults
بيانات. إذا تم استيفاء الشرط، يتم تعيين المتغير isCache
إلى true
. بعد ذلك، تستدعي طريقة parse()
لكائن JSON
بوسيط cacheResults
. تقوم طريقة parse()
بتحويل بيانات السلسلة JSON إلى كائن JavaScript. بعد جرى تحليل الJSON، تستدعي طريقة send()
التي تأخذ كائنًا يحتوي على خاصية fromCache
معتمدة على المتغير isCached
. تقوم الطريقة بإرسال الاستجابة إلى العميل.
إذا لم تجد طريقة get()
في وحدة node-redis
أي بيانات في الذاكرة المؤقتة، يتم تعيين المتغير cacheResults
إلى null
. نتيجة لذلك، يُقَدَّر بأن البيان if
كاذبًا. عند حدوث ذلك، يتخطى التنفيذ إلى كتلة else
حيث تستدعي دالة fetchApiData()
لاسترجاع البيانات من الواجهة البرمجية. ومع ذلك، بمجرد عودة البيانات من الواجهة البرمجية، لا يتم حفظها في Redis.
لحفظ البيانات في ذاكرة التخزين المؤقت Redis، يجب عليك استخدام طريقة set()
لوحدة node-redis
لحفظها. للقيام بذلك، قم بإضافة السطر المميز كالتالي:
Dentro منطقة ال else
, عندما يتم استرجاع البيانات, تقوم بإستدعاء الطريقة set()
من وحدة node-redis
لحفظ البيانات في Redis تحت اسم المفتاح من قيمة المتغير species
.
الطريقة set()
تأخذ معها مدخلتين, اللذان هما: زوج مفتاح قيمة species
و JSON.stringify(results)
.
المدخل الأول, species
, هو المفتاح الذي سيتم حفظ البيانات تحته في Redis. تذكر species
هو معين إلى القيمة المرسلة إلى النقطة النهائية التي قمت بتعريفها. على سبيل المثال, عندما تزور /fish/red-snapper
, species
يتم تعيينه إلى red-snapper
, الذي سيكون المفتاح في Redis.
المدخل الثاني, JSON.stringify(results)
, هو القيمة للمفتاح. في المدخل الثاني, تستدعي طريقة stringify()
من JSON
بالمتغير results
كمدخل, الذي يحتوي على البيانات التي تم إرجاعها من الAPI. الطريقة تحول JSON إلى سلسلة نصية; هذا هو السبب في أنه, عندما استرجعت البيانات من الذاكرة المخبأة باستخدام طريقة get()
من وحدة node-redis
سابقًا, قمت باستدعاء طريقة JSON.parse
بالمتغير cacheResults
كمدخل.
ملفك الكامل الآن سيبدو كما يلي:
حفظ واخرج ملفك, وقم بتشغيل server.js
بإستخدام الأمر node
:
بمجرد بدء تشغيل الخادم, قم بتحديث http://localhost:3000/fish/red-snapper
في متصفحك.
لاحظ أن fromCache
ما زالت معينة إلى false
:
الآن قم بتحديث الصفحة مرة أخرى لرؤية أن fromCache
مضبوطة إلى true
:
قم بتحديث الصفحة خمس مرات وعد إلى الطرفية. سيكون مخرجاتك مشابهة لما يلي:
OutputApp listening on port 3000
Request sent to the API
الآن، تم تسجيل Request sent to the API
مرة واحدة فقط بعد عدة عمليات تحديث للرابط، متناقضة مع القسم الأخير حيث تم تسجيل الرسالة لكل عملية تحديث. تؤكد هذه المخرجات أن طلب واحد فقط تم إرساله إلى الخادم وبالتالي، يتم جلب البيانات من Redis.
لتأكيد مزيد من أن البيانات مخزنة في Redis، قم بإيقاف الخادم باستخدام CTRL+C
. اتصل بعميل خادم Redis باستخدام الأمر التالي:
استرجاع البيانات تحت المفتاح red-snapper
:
ستكون مخرجاتك مشابهة لما يلي (تم تحريرها لأسباب الاختصار):
Output"[{\"Fishery Management\":\"<ul>\\n<li><a...3\"}]"
تُظهر المخرجات النسخة المُسلسلة للبيانات JSON التي يقوم API بإرجاعها عند زيارة نقطة النهاية /fish/red-snapper
، مما يؤكد أن بيانات الـ API مخزنة في ذاكرة التخزين المؤقت Redis.
اخرج من عميل خادم Redis:
الآن بما أنه يمكنك تخزين البيانات من API، يمكنك أيضًا تعيين صلاحية الذاكرة المؤقتة.
الخطوة 4 — تنفيذ صلاحية الذاكرة المؤقتة
عند تخزين البيانات المؤقتة، تحتاج إلى معرفة مدى تغيير البيانات. بعض بيانات واجهة برمجة التطبيقات تتغير في دقائق؛ بينما تتغير البيانات الأخرى في ساعات، أسابيع، أشهر، أو سنوات. ضبط مدة التخزين المؤقت المناسبة يضمن أن تقدم تطبيقك بيانات محدثة لمستخدميك.
في هذه الخطوة، ستقوم بتحديد صلاحية التخزين المؤقت لبيانات واجهة برمجة التطبيقات التي تحتاج إلى تخزينها في ريديس. عند انتهاء صلاحية الذاكرة المؤقتة، سيُرسَل تطبيقك طلبًا إلى واجهة برمجة التطبيقات لاسترداد البيانات الأخيرة.
تحتاج إلى الرجوع إلى وثائق واجهة برمجة التطبيقات الخاصة بك لتحديد الوقت الصحيح لانتهاء صلاحية التخزين المؤقت. ستذكر معظم الوثائق مدى تحديث البيانات بانتظام. ومع ذلك، هناك بعض الحالات حيث لا تقدم الوثائق هذه المعلومات، لذا قد تضطر إلى التخمين. يمكن أن يُظهر فحص خاصية last_updated
في نقاط نهاية واجهة برمجة التطبيقات المختلفة كيفية تحديث البيانات بانتظام.
بمجرد اختيارك لمدة التخزين المؤقت، عليك تحويلها إلى ثواني. لغرض التوضيح في هذا البرنامج التعليمي، ستقوم بتعيين مدة التخزين المؤقت إلى 3 دقائق أو 180 ثانية. ستجعل هذه المدة العينية عملية اختبار وظيفة مدة التخزين المؤقتة أسهل.
لتنفيذ مدة صلاحية التخزين المؤقت، افتح ملف server.js
:
أضف الكود المظلل:
في طريقة set()
في وحدة node-redis
، قم بتمرير وسيطًا ثالثًا من كائن بالخصائص التالية:
EX
: يقبل قيمة بمدة التخزين المؤقت بالثواني.NX
: عند تعيينها علىtrue
، فإنها تضمن أن طريقةset()
يجب أن تقوم فقط بتعيين مفتاح لا يوجد بالفعل في ريديس.
احفظ وأغلق ملفك.
العودة إلى عميل خادم Redis لاختبار صلاحية التخزين المؤقت:
حذف المفتاح red-snapper
في Redis:
الخروج من عميل Redis:
الآن، قم ببدء خادم التطوير باستخدام أمر node
:
انتقل إلى متصفحك وقم بتحديث عنوان http://localhost:3000/fish/red-snapper
. لمدة ثلاث دقائق قادمة، إذا قمت بتحديث العنوان، يجب أن يكون الإخراج في الطرفية متسقًا مع الإخراج التالي:
OutputApp listening on port 3000
Request sent to the API
بعد مرور ثلاث دقائق، قم بتحديث العنوان في متصفحك. في الطرفية، يجب أن ترى أن “تم إرسال الطلب إلى الواجهة البرمجية” قد تم تسجيله مرتين.
OutputApp listening on port 3000
Request sent to the API
Request sent to the API
يوضح هذا الإخراج أن التخزين المؤقت قد انتهت صلاحيته، وتم إرسال طلب إلى الواجهة البرمجية مرة أخرى.
يمكنك إيقاف خادم Express الآن.
الآن بعد أن يمكنك تحديد صلاحية التخزين المؤقت، ستقوم بتخزين البيانات باستخدام middleware التالي.
الخطوة 5 — تخزين البيانات في middleware
في هذه الخطوة، ستستخدم middleware Express لتخزين البيانات. Middleware هو وظيفة يمكنها الوصول إلى كائن الطلب، كائن الاستجابة، ودالة استدعاء يجب تشغيلها بعد تنفيذه. الوظيفة التي تشغل بعد middleware لديها أيضًا الوصول إلى كائنات الطلب والاستجابة. عند استخدام middleware، يمكنك تعديل كائنات الطلب والاستجابة أو إرجاع استجابة للمستخدم في وقت سابق.
لاستخدام الوسيطة في تطبيقك للتخزين المؤقت، ستقوم بتعديل دالة المعالج getSpeciesData()
لاسترجاع البيانات من واجهة برمجة التطبيقات وتخزينها في ريديس. ستقوم بنقل جميع الشفرة التي تبحث عن البيانات في ريديس إلى دالة الوسيطة cacheData
.
عند زيارة نقطة النهاية /fish/:species
، ستقوم دالة الوسيطة بالتشغيل أولاً للبحث عن البيانات في التخزين المؤقت؛ إذا تم العثور عليها، ستعيد استجابة، ولن يتم تشغيل دالة getSpeciesData
. ومع ذلك، إذا لم تجد الوسيطة البيانات في التخزين المؤقت، فسوف تستدعي دالة getSpeciesData
لاسترجاع البيانات من واجهة برمجة التطبيقات وتخزينها في ريديس.
أولاً، افتح ملف server.js
:
ثم، احذف الشفرة المظللة:
في دالة getSpeciesData()
، قم بإزالة جميع الشفرة التي تبحث عن البيانات المخزنة في ريديس. كما قم بإزالة المتغير isCached
حيث أن دالة getSpeciesData()
ستقوم فقط بالحصول على البيانات من واجهة برمجة التطبيقات وتخزينها في ريديس.
بمجرد أن يتم إزالة الشفرة، قم بتعيين fromCache
إلى false
كما هو مظلل أدناه، بحيث تبدو دالة getSpeciesData()
كما يلي:
تقوم دالة getSpeciesData()
بإسترجاع البيانات من واجهة برمجة التطبيقات، تخزينها في التخزين المؤقت، وتعيد استجابة للمستخدم.
بعد ذلك، أضف الشفرة التالية لتعريف دالة الوسيطة لتخزين البيانات في ريديس:
تأخذ وظيفة middleware cacheData()
ثلاثة مُعاملات: req
و res
و next
. في الكتلة try
، تقوم الوظيفة بالتحقق مما إذا كانت القيمة في متغير species
لديها بيانات مخزنة في Redis تحت مفتاحها. إذا كانت البيانات موجودة في Redis، يتم إرجاعها وتعيينها إلى متغير cacheResults
.
بعد ذلك، تقوم البيانات بالتحقق في البيانات إذا كانت موجودة. يتم حفظ البيانات في المتغير results
إذا كانت القيمة صحيحة. بعد ذلك، يستخدم الوسيطة الوسيطة الوظيفة send()
لإرجاع كائن بالخصائص fromCache
المعينة على true
و data
المعينة على المتغير results
.
ومع ذلك، إذا كانت قيمة الكائن if
تقوم بالتقييم على أنها خاطئة، يتم تحويل التنفيذ إلى الكتلة else
. ضمن الكتلة else
، تقوم بالاتصال بـ next()
، الذي يمر بالتحكم إلى الوظيفة التالية التي يجب تنفيذها بعد ذلك.
لجعل وظيفة cacheData()
للوسيطة تمرر التحكم إلى الوظيفة getSpeciesData()
عند استدعاء next()
، قم بتحديث الطريقة get()
في وحدة express
وفقًا لذلك:
الآن تأخذ الطريقة get()
cacheData
كمُعامل ثاني، وهي الوسيطة التي تبحث عن البيانات المخزنة في Redis وتُرجع استجابة عند العثور عليها.
الآن، عند زيارة النقطة النهائية /fish/:species
، يُنفَّذ cacheData()
أولاً. إذا تمت مضاعفة البيانات، سيُرجَع الاستجابة، ويُنتهي دورة الطلب والاستجابة هنا. ومع ذلك، إذا لم يتم العثور على بيانات في المخزن، سيتم استدعاء getSpeciesData()
لاسترجاع البيانات من الواجهة البرمجية، وتخزينها في المخزن، وإرجاع استجابة.
الملف الكامل سيبدو الآن هكذا:
احفظ وأخرج من الملف.
للاختبار الصحيح للتخزين المؤقت، يمكنك حذف مفتاح red-snapper
في Redis. للقيام بذلك، انتقل إلى عميل Redis:
أزل مفتاح red-snapper
:
اخرج من عميل Redis:
الآن، قم بتشغيل ملف server.js
:
بمجرد بدء تشغيل الخادم، عد إلى المتصفح وقم بزيارة http://localhost:3000/fish/red-snapper
مرة أخرى. قم بتحديثه مرات عديدة.
ستُسجَّل رسالة في الطرفية تفيد بإرسال طلب إلى الواجهة البرمجية. سيخدم الوسيط cacheData()
جميع الطلبات للدقائق الثلاث القادمة. ستبدو النتيجة مشابهة لهذا إذا قمت بتحديث عنوان URL بشكل عشوائي في فترة زمنية تبلغ أربع دقائق:
OutputApp listening on port 3000
Request sent to the API
Request sent to the API
السلوك متسق مع كيفية عمل التطبيق في القسم السابق.
يمكنك الآن تخزين البيانات في Redis باستخدام الوسيط.
الختام
في هذا المقال، قمت ببناء تطبيق يقوم بجلب البيانات من واجهة برمجة التطبيقات (API) ويقوم بإرجاع البيانات كاستجابة للعميل. ثم قمت بتعديل التطبيق لتخزين استجابة API في Redis في الزيارة الأولى وتقديم البيانات من الذاكرة المؤقتة لجميع الطلبات التالية. ثم قمت بتعديل مدة التخزين المؤقت لتنتهي بعد مرور مدة معينة من الزمن، ومن ثم استخدمت الوسيطة للتعامل مع استرجاع البيانات المخزنة مؤقتًا.
كخطوة مقبلة، يمكنك استكشاف وثائق Node Redis لتعلم المزيد حول الميزات المتاحة في وحدة node-redis
. يمكنك أيضًا قراءة وثائق Axios و Express للنظر العميق في المواضيع المغطاة في هذا البرنامج التعليمي.
لمواصلة بناء مهارتك في Node.js، انظر سلسلة كيفية البرمجة في Node.js.
Source:
https://www.digitalocean.com/community/tutorials/how-to-implement-caching-in-node-js-using-redis