WebSocketStream: دمج مجموعات البث مع واجهة برمجة تطبيقات WebSocket

يمكنك منع تطبيقك من الانغماس في رسائل WebSocket أو إغراق خادم WebSocket بالرسائل من خلال تطبيق الضغط العكسي.

الخلفية

واجهة برمجة التطبيقات WebSocket API

واجهة برمجة التطبيقات WebSocket API لتوفير واجهة JavaScript لبروتوكول WebSocket، مما يجعل من الممكن فتح جلسة تواصل تفاعلية ثنائية الاتجاه بين متصفح المستخدم والخادم. باستخدام واجهة برمجة التطبيقات هذه، يمكنك إرسال الرسائل إلى خادم وتلقّي ردود مستندة إلى الحدث. دون البحث في الخادم عن الرد.

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

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

مشكلة واجهة برمجة التطبيقات WebSocket API الحالية

يستحيل تطبيق ضغط رجعي على الرسائل المُستلَمة

في واجهة برمجة التطبيقات WebSocket API الحالية، يحدث التفاعل مع رسالة WebSocket.onmessage، EventHandler يتم استدعاءه عند استلام رسالة من الخادم.

لنفترض أن لديك تطبيقًا يحتاج إلى إجراء عمليات معالجة مكثّفة للبيانات. عند تلقي رسالة جديدة. ربما تقوم بإعداد التدفق مشابه للتعليمة البرمجية أدناه، وبما أنك await نتيجة المكالمة process()، ينبغي أن تكون على ما يرام، أليس كذلك؟

// A heavy data crunching operation.
const process = async (data) => {
  return new Promise((resolve) => {
    window.setTimeout(() => {
      console.log('WebSocket message processed:', data);
      return resolve('done');
    }, 1000);
  });
};

webSocket.onmessage = async (event) => {
  const data = event.data;
  // Await the result of the processing step in the message handler.
  await process(data);
};

خطأ! تكمن مشكلة واجهة برمجة التطبيقات WebSocket API الحالية في عدم توفُّر طريقة لتطبيق الضغط العكسي. عندما تصل رسائل بسرعة تفوق سرعة معالجتها عبر طريقة process()، فإن عملية العرض ستملأ الذاكرة من خلال تخزين هذه الرسائل مؤقتًا، لا تستجيب بسبب استخدام وحدة المعالجة المركزية 100% أو كليهما.

تطبيق الضغط العكسي على الرسائل المرسلة ليس مريحًا

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

ما هي واجهة برمجة التطبيقات WebSocketStream API؟

تتعامل واجهة برمجة التطبيقات WebSocketStream API مع مشكلة الضغط العكسي غير الموجود أو غير المريح من خلال دمج مجموعات البث مع واجهة برمجة التطبيقات WebSocket API وهذا يعني أنه يمكن تطبيق الضغط العكسي "مجانًا"، بدون أي تكلفة إضافية.

حالات الاستخدام المقترَحة لواجهة برمجة التطبيقات WebSocketStream API

تشمل أمثلة المواقع الإلكترونية التي يمكنها استخدام واجهة برمجة التطبيقات هذه ما يلي:

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

الوضع الحالي

الخطوة الحالة
1. إنشاء شرح مكتمل
2. إنشاء مسودة أولية للمواصفات قيد التقدّم
3- جمع الملاحظات التكرار التحسيني للتصميم قيد التقدّم
4. مرحلة التجربة والتقييم مكتمل
5- إطلاق Not started

كيفية استخدام واجهة برمجة التطبيقات WebSocketStream API

مثال تمهيدي

تستند واجهة برمجة التطبيقات WebSocketStream API إلى الوعود، ما يجعل التعامل معها تجربة طبيعية. في عالم JavaScript حديث. عليك البدء بإنشاء WebSocketStream جديد وتمريره عنوان URL لخادم WebSocket. بعد ذلك، انتظر حتى يصبح الاتصال opened، مما يؤدي إلى ReadableStream و/أو a WritableStream

من خلال استدعاء ReadableStream.getReader() فستحصل أخيرًا على ReadableStreamDefaultReader, ويمكنك بعد ذلك read() البيانات من إلى أن ينتهي البث، أي إلى أن يعرض كائنًا من النموذج {value: undefined, done: true}.

وفقًا لذلك، من خلال استدعاء WritableStream.getWriter() فستحصل أخيرًا على WritableStreamDefaultWriter, ويمكنك بعد ذلك write() البيانات إليه.

  const wss = new WebSocketStream(WSS_URL);
  const {readable, writable} = await wss.opened;
  const reader = readable.getReader();
  const writer = writable.getWriter();

  while (true) {
    const {value, done} = await reader.read();
    if (done) {
      break;
    }
    const result = await process(value);
    await writer.write(result);
  }

الضغط العكسي

ماذا عن ميزة الضغط العكسي الموعودة؟ كما ذكرتُ أعلاه، يمكنك الحصول عليه "مجانًا"، ولا يلزم اتخاذ خطوات إضافية. إذا استغرقت عملية process() وقتًا إضافيًا، لن يتم استهلاك الرسالة التالية إلا بعد أن يصبح مسار التعلّم جاهزًا. بالمثل، خطوة WritableStreamDefaultWriter.write() ستستمر في التنفيذ فقط إذا كان ذلك إجراءً آمنًا.

أمثلة متقدمة

الوسيطة الثانية WebSocketStream هي عبارة عن حقيبة خيارات للسماح بتمديدها في المستقبل. الخيار الوحيد حاليًا هو protocols، والتي تعمل بنفس طريقة عمل الوسيطة الثانية إلى الدالة الإنشائية WebSocket:

const chatWSS = new WebSocketStream(CHAT_URL, {protocols: ['chat', 'chatv2']});
const {protocol} = await chatWSS.opened;

protocol المحددة بالإضافة إلى extensions المحتملة هي جزء من القاموس. المتاحة من خلال وعد WebSocketStream.opened. يوفر هذا الوعد جميع المعلومات حول الاتصال المباشر، لأنه ليس ذا صلة إذا فشل الاتصال.

const {readable, writable, protocol, extensions} = await chatWSS.opened;

معلومات حول اتصال WebSocketStream المغلق

كانت المعلومات التي كانت متاحة من WebSocket.onclose و أحداث WebSocket.onerror في واجهة برمجة التطبيقات WebSocket API متاحة الآن من خلال وعد WebSocketStream.closed. يرفض الوعد في حالة إغلاق غير نظيف، وبخلاف ذلك، يتم حلها إلى الرمز والسبب الذي يرسله الخادم.

يتم توضيح جميع رموز الحالة المحتملة ومعانيها في قائمة تضم رموز الحالة CloseEvent.

const {code, reason} = await chatWSS.closed;

إغلاق اتصال WebSocketStream

يمكن إغلاق WebSocketStream باستخدام AbortController لذلك، عليك تمرير AbortSignal إلى الدالة الإنشائية WebSocketStream.

const controller = new AbortController();
const wss = new WebSocketStream(URL, {signal: controller.signal});
setTimeout(() => controller.abort(), 1000);

ويمكنك بدلاً من ذلك استخدام الطريقة WebSocketStream.close()، ولكن الغرض الرئيسي منها هو السماح بتحديد الرمز والسبب الذي يتم إرساله إلى الخادم.

wss.close({code: 4000, reason: 'Game over'});

التحسين التدريجي وإمكانية التشغيل التفاعلي

Chrome هو حاليًا المتصفّح الوحيد الذي يمكن من خلاله تنفيذ واجهة برمجة التطبيقات WebSocketStream API. بالنسبة إلى التشغيل التفاعلي مع واجهة برمجة التطبيقات WebSocket API الكلاسيكية، لا يمكن تطبيق الضغط العكسي على الرسائل المستلمة. يمكن تطبيق ضغط رجعي على الرسائل المرسلة، ولكنه يتضمن استطلاع رأي WebSocket.bufferedAmount غير فعالة وغير مريحة.

رصد الميزات

للتحقّق مما إذا كانت واجهة برمجة التطبيقات WebSocketStream API متوافقة، يمكنك استخدام:

if ('WebSocketStream' in window) {
  // `WebSocketStream` is supported!
}

عرض توضيحي

في المتصفحات المتوافقة، يمكنك رؤية واجهة برمجة التطبيقات WebSocketStream API وهي قيد التشغيل في إطار iframe المضمّن. أو مباشرةً من خلال Glitch

ملاحظات

يريد فريق Chrome معرفة رأيك بشأن تجاربك في استخدام واجهة برمجة التطبيقات WebSocketStream API.

أخبِرنا عن تصميم واجهة برمجة التطبيقات

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

الإبلاغ عن مشكلة في التنفيذ

هل واجهت مشكلة في التنفيذ في Chrome؟ أم أن التنفيذ يختلف عن المواصفات؟ يُرجى الإبلاغ عن الخطأ على new.crbug.com. تأكد من تضمين أكبر قدر ممكن من التفاصيل، وتعليمات بسيطة لإعادة الإنتاج، وأدخِل Blink>Network>WebSockets في مربع المكوّنات. تعمل ميزة الخطأ بشكلٍ رائع لمشاركة حافظات إعادة الإنتاج السريعة والسهلة.

إظهار الدعم لواجهة برمجة التطبيقات

هل لديك خطة لاستخدام واجهة برمجة التطبيقات WebSocketStream API؟ يساعد الدعم العام فريق Chrome على تحديد أولويات الميزات ويعرض لموردي المتصفحات الآخرين مدى أهمية دعمهم

إرسال تغريدة إلى @ChromiumDev باستخدام علامة التصنيف #WebSocketStream عليك إعلامنا بمكان تطبيقك وطريقة استخدامه

روابط مفيدة

شكر وتقدير

نفّذ آدم رايس واجهة برمجة التطبيقات WebSocketStream API. يوتاكا هيرانو صورة رئيسية بواسطة دان مويج على إزالة البداية