اذهب إلى المحتوى

إنجاز واجهة برمجية في جافا سكريبت تعتمد على الوعود


ابراهيم الخضور

شرحنا في المقال السابق طريقة استخدام واجهات برمجة التطبيقات التي تعيد الوعود 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

اقرأ أيضًا:


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...