شرحنا في المقال السابق طريقة استخدام واجهات برمجة التطبيقات التي تعيد الوعود promises، وسنتحدث في هذا المقال عن تعريف الواجهات البرمجية التي تعيد وعودًا في لغة البرمجة جافا سكريبت، ونلقي نظرة على كيفية إنجاز هذه الواجهات البرمجية بأنفسنا، وعلى الرغم من أن مهمة كهذه ليست شائعة الاستخدام كثيرًا لكن من المفيد لك معرفتها.
ملاحظة: عند تنفيذ واجهة برمجة تطبيقات معتمدة على الوعود promise-based API ستحتاج لأن نغلّف عملية غير متزامنة (مثل اﻷحداث events، أو دوال رد النداء callbacks، أو نموذج يعمل على تمرير الرسائل message-passing model) وسيكون عليك هيكلة كائن Promise للتعامل مع حالات نجاح تنفيذ هذه العملية resolve أو إخفاقها reject.
تنفيذ الواجهة البرمجية ()alarm
ما سنفعله في هذا المثال هو إنجاز واجهة برمجية لمنبّه تُدعى ()alarm
. تقبل هذه الواجهة وسيطًا هو اسم الشخص الذي ستوقظه كما تأخذ وسيطًا آخر هي الفترة الزمنية التي ينتظرها المنبه بالميلي ثانية قبل إيقاظ الشخص. بعد ذلك تُرسل الدالة الرسالة "Wake up" (أي استيقظ) يليها اسم الشخص.
تغليف الدالة ()setTimeout
نستخدم الواجهة ()setTimeout
في إنجاز واجهتنا ()alarm
، وتأخذ هذه الواجهة وسيطين: دالة تستدعيها عند بلوغ زمن التنبيه، واﻵخر زمن التنبيه بالميلي ثانية. وعندما تُستدعى الواجهة ()setTimeout
، تبدأ بالعد وصولًا إلى زمن التنبيه وتستدعي عندها الدالة التي مررناها إليها.
نستدعي في مثالنا التالي الدالة ()setTimeout
مع وسيطيها دالة رد النداء وزمن التنبيه الذي سيكون 1000 ميلي ثانية. إليك شيفرة HTML:
<button id="set-alarm">Set alarm</button> <div id="output"></div>
ثم شيفرة جافا سكريبت:
const output = document.querySelector("#output"); const button = document.querySelector("#set-alarm"); function setAlarm() { setTimeout(() => { output.textContent = "Wake up!"; }, 1000); } button.addEventListener("click", setAlarm);
إليك نتيجة التنفيذ:
الدالة البانية ()Promise
تُعيد الدالة وعدًا Promise
يُنجز عندما ينقضي الوقت المخصص للمنبّه، ويمرر الرسالة إلى معالج ()then
بينما يُرفض الوعد إن كان زمن التنبيه سالبًا.
إن المفتاح الرئيسي للعمل هنا هي الدالة البانية ()Promise
التي تأخذ دالة استدعاء كوسيط لها وندعوها دالة منفّذة executer
وعليك كتابة شيفرة هذه الدالة عند إنشاء وعد جديد. وتأخذ الدالة المنفذة دالتين كوسيط لها تُدعيان تقليديًا الدالة resolve
والدالة reject
. تستدعي الدالة المنفذة الدالة غير المتزامنة فإن أنجز الوعد ستُستدعى الدالة resolve
وإن أخفق تُستدعى الدالة reject
. إما إذا رمت الدالة المنفذة خطأً، ستُستدعى reject
تلقائيًا. باﻹمكان تمرير أية قيم إلى الدالتين resolve
و reject
.
لذا بإمكانك كتابة شيفرة الواجهة ()alarm
كالتالي:
function alarm(person, delay) { return new Promise((resolve, reject) => { if (delay < 0) { throw new Error("Alarm delay must not be negative"); } setTimeout(() => { resolve(`Wake up, ${person}!`); }, delay); }); }
تُنشئ الدالة السابقة وعدًا Promise
وتعيده، وضمن الدالة المنفذة:
-
نتحقق من قيمة زمن التنبيه
delay
حتى لا تكون سالبة. -
نستدعي الدالة
()setTimeout
ونمرر لها القيمةdelay
، ومن ثم تُستدعى دالة رد النداء الموجودة ضمن الدالة السابقة عند انقضاء الوقت المحدد ومن ثم تٌستدعى الدالةresolve
بعد أن نمرر لها الرسالة"!Wake up"
.
استخدام الواجهة البرمجية ()alarm
من المفترض أن تكون الشيفرة التالية مألوفة من المقال السابق. إذ نستطيع استدعاء الواجهة ()alarm
ومن ثم نستدعي ()then
و ()catch
لكائن الوعد الذي تعيده للتعامل مع حالتي إنجاز الوعد أو رفضه:
const name = document.querySelector("#name"); const delay = document.querySelector("#delay"); const button = document.querySelector("#set-alarm"); const output = document.querySelector("#output"); function alarm(person, delay) { return new Promise((resolve, reject) => { if (delay < 0) { throw new Error("Alarm delay must not be negative"); } setTimeout(() => { resolve(`Wake up, ${person}!`); }, delay); }); } button.addEventListener("click", () => { alarm(name.value, delay.value) .then((message) => (output.textContent = message)) .catch((error) => (output.textContent = `Couldn't set alarm: ${error}`)); });
إليك نتيجة التنفيذ:
جرب تحديد قيم مختلفة لكل من person
و delay
وحاول تمرير قيم delay
سالبة وراقب الخرج الناتج.
استخدام التعليمين async
و await
مع الواجهة البرمجية alarm()
طالما أن الواجهة ()alarm
تعيد وعدًا، نستطيع أن نطبق عليه ما يُطبق على أي وعد آخر، مثل ربطه ضمن سلسلة وعود promise-chain أو استخدام ()all.
وكذلك wait
/async
.
const name = document.querySelector("#name"); const delay = document.querySelector("#delay"); const button = document.querySelector("#set-alarm"); const output = document.querySelector("#output"); function alarm(person, delay) { return new Promise((resolve, reject) => { if (delay < 0) { throw new Error("Alarm delay must not be negative"); } setTimeout(() => { resolve(`Wake up, ${person}!`); }, delay); }); } button.addEventListener("click", async () => { try { const message = await alarm(name.value, delay.value); output.textContent = message; } catch (error) { output.textContent = `Couldn't set alarm: ${error}`; } });
إليك نتيجة التنفيذ:
الخلاصة
تعرفنا في هذا المقال على كيفية استخدام الواجهات البرمجية التي تعيد وعودًا promises، وألقينا نظرة على كيفية إنجاز الواجهات البرمجية التي تعيد الوعود من خلال مثال تطبيقي ينجز واجهة منبه للمستخدم بعد انقضاء وقت معين.
ترجمة -وبتصرف- للمقال: How to implement a promise-based API
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.