واجهة برمجة تطبيقات Web Locks

تنسيق العمل واستخدام الموارد بين العمليات المختلفة

حان وقت القفل

الوظائف غير المتزامنة في جافا سكريبت ليست متوازية حقًا. بدءًا من ES2017 ، تدعم Javascript مكالمات الوظائف المتزامنة. تم تلخيص الاختلاف بشكل جيد للغاية بواسطة Madhavan Nagarajan في البيان التالي (يمكن العثور على الرابط في الملحق).

التزامن هو التعامل مع الكثير من الأشياء في وقت واحد. التوازي هو القيام بالكثير من الأشياء في وقت واحد.

يتم تقليل تنفيذ التزامن في جافا سكريبت في وظائفها للسماح باستخدام واجهة برمجة تطبيقات بسيطة وقوية للغاية. لا يمكن مقاطعة الوظائف غير المتزامنة وليس لها مفهوم للخصائص المتغيرة عند التعامل مع الوصول إلى نفس المتغير عن طريق استدعاءات غير متزامنة مختلفة. التنفيذ التفصيلي لوظائف ES2017 غير المتزامنة خارج نطاق هذه المقالة ، ولكن النقطة الرئيسية التي أريد أن أتطرق إليها هي أنه حتى الآن ، لم يتم تضمين التوازي في جافا سكريبت والويب ، وبالتالي ، لا توجد معالجة خاصة للطفرات المتوازية في نفس الكيان. لكن هذا يتغير الآن مع تقديم "Web Locks API".

واحد للجميع والجميع للواحد

الآن بعد أن أصبحت تطبيقات الويب التقدمية تقدم لك بنى حقيقية متعددة الخيوط مع تقديم WebWorkers و ServiceWorker ، فقد تغيرت الأمور. التوازي الحقيقي ممكن في تطبيقات الويب ، وبالتالي تنشأ الرغبة في أدوات أكثر تعقيدًا للتعامل مع الكود الموازي.

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

المورد هو مجرد مساحة اسم محددة بسلسلة. كما أن طلبك للوصول إلى المورد بسيط للغاية ، حيث أنك تحتاج فقط إلى المعرف واستدعاء الوظيفة ، على الأرجح غير متزامن ، لتنفيذ "Web Lock API". عند انتهاء إحدى الوظائف غير المتزامنة ، يتم تحرير القفل ويمكن للطلبات الأخرى الوصول إليه مرة أخرى.

/*
 * A simple demonstration of the Web Lock API.
 * Note that this example has been taken from
 * MDN's awesome documentation, linked in the
 * addendum.
 */
async function foo(){
  // A common async function that you already know.
  const data = await getData();

  // Request the lock.
  // Note that we can simply await the locked call!
  await navigator.locks.request('lock_resource_id', async lock => {
    // The lock has been acquired.
    // At this point, this call has exlusive access 
    // to the resource 'lock_resource_id'.
    await updateDb(data);
    // Now the lock will be released.
  });
  
  // The lock has been released.
  // Continuse with plain async calls.
  await updateUi();
}

نظرًا للحالة التجريبية لواجهة برمجة التطبيقات الجديدة هذه ، يتعين عليك معاملتها كميزة اختيارية في التعليمات البرمجية الخاصة بك مع توفر احتياطي صالح.

/**
 * Due to the usage of web locks in core parts
 * of your app, actually using the API this way
 * might introduce more problems then it could solve.
 * 
 * Therefore a thorough specification in your app
 * has to be implementation before using this feature.
 */
async function update(){
  if(navigator?.locks){
    // Run logic with lock.
  } else {
    // Use fallback.
  }
}

لتوضيح واجهة برمجة التطبيقات الجديدة هذه بشكل أفضل ، سنلقي نظرة على مثال بسيط. لنفترض أن لديك PWA متعدد الخيوط مع عمليتك الرئيسية واثنين من WebWorkers. يستخدم تطبيقك أيضًا IndexDB ، مع رمز مخصص يقوم بمزامنة التغييرات من وإلى قاعدة البيانات مع السحابة. باستخدام "Web Lock API" في هذا السيناريو ، يمكن لكل عملية طلب الوصول إلى القفل المحدد لمزامنة التغييرات في قاعدة البيانات ، والتأكد من عدم تشغيل أي طفرات أخرى أثناء هذه المكالمة.

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

الكثير لنتعلمه

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

الاقتراحات

ذات صلة

ملحق

اللغات