باختصار حول قنوات الإعادة الملحمية

مساء الخير أيها الأصدقاء الأعزاء.


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


لذلك دعونا نبدأ.


مشكلة نموذج الساعة والشوكة


لنفترض أن لدينا نموذجًا منتظمًا للساعة والشوكة ، من النموذج التالي:


import { take, fork } from 'redux-saga/effects' function* watchRequest() { while (true) { const {payload} = yield take('INIT_REQUEST'); // ,     yield fork(makeRequest, payload); } } function* makeRequest(payload) { //   } 

هذا النهج سيء لأنه عند التقاط العديد من أحداث INIT_REQUEST التي تتبع واحدة تلو الأخرى ، سيتم تنفيذ العديد من عمليات تنفيذ makeRequest ، على التوالي. وهذا بدوره يمكن أن يسبب لهم "العرق".


وهنا تأتي آلية القناة لمساعدتنا.


تحتوي القنوات على مخازن مؤقتة ، مما يساعد في ترتيب الأحداث الواردة (على سبيل المثال ، INIT_REQUEST ) ، وتنظيم التنفيذ المتسلسل (على سبيل المثال ، سيتم تنفيذ makeRequest عدة مرات بالتتابع).


بمعنى تقريبي ، تشكل القنوات قائمة انتظار FIFO للتنفيذ المتسلسل.


التصنيف حسب مصدر الحدث:


  • channel - الأحداث في قائمة الانتظار يدويا باستخدام put .
  • actionChannel - يتم actionChannel الأحداث بالقرب من متجر redux ؛
  • eventChannel - مصدر حدث خارجي ، غالبًا ما يكون مقبس ويب ؛

لذلك ، سوف نقوم بتحليل كل باختصار.


أكثر على القناة


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


 channel([buffer]) 

يحتوي على وسيطة buffer واحد - المخزن المؤقت المتراكم (سوف نقوم بفحص المخازن المؤقتة بمزيد من التفاصيل أدناه).


المزيد عن actionChannel


يتم استخدامه غالبًا عندما يكون من الضروري الرد على الأحداث من متجر الإعادة.


 actionChannel(pattern, [buffer]) 

يستغرق حجتين:


  • pattern - نمط الأحداث المطلوبة ، وكذلك take ؛
  • buffer - تراكم العازلة.

مثال موجز للاستخدام:


 import { take, actionChannel, call } from 'redux-saga/effects' function* watchRequest() { const requestChannel = yield actionChannel('INIT_REQUEST') while (true) { const {payload} = yield take(requestChannel); //      yield call(makeRequest, payload); } } function* makeRequest(payload) { //   } 

المزيد عن eventChannel


عادة ما يقومون بحل مشكلة الاتصال عبر مقبس الويب من خلالها.


 eventChannel(subscribe, [buffer], [matcher]) 

يستغرق ثلاث حجج:


  • subscribe هو وظيفة تقوم بتهيئة مصدر حدث خارجي (في المثال أدناه ، setTimeout). في الوسائط ، يسمى رد الاتصال باعث ، والذي سيتم استدعاؤه عند الضرورة لإرسال البيانات إلى القناة من المصدر. عودة يجب إلغاء الاشتراك وظيفة ؛
  • buffer - تراكم العازلة.
  • matcher - وظيفة لتصفية الرسائل الواردة.

مثال موجز للاستخدام:


 import { eventChannel, END } from 'redux-saga' import { take, put, call } from 'redux-saga/effects' function initSocketChannel(query) { return eventChannel(emitter => { //     web socket const handshakeTimeoutId = setTimeout(() => { emitter('handshake - ok'); }, 100); const messageTimeoutId = setTimeout(() => { emitter('message'); }, 500); const endTimeoutId = setTimeout(() => { emitter(END); }, 1000); //     return () => { clearTimeout(handshakeTimeoutId); clearTimeout(messageTimeoutId); clearTimeout(endTimeoutId); } } ) } export function* saga() { const chan = yield call(initSocketChannel, query) try { while (true) { const message = yield take(chan); //    END   brake console.log(`socket : ${message}`) } } finally { console.log('socket terminated') } } 

بالتأكيد لاحظت وجود ثابت END - وهذا هو العمل ، مما يعني نهاية التواصل مع القناة.


في التعليمات البرمجية المصدر ، يتم تمثيل redux-saga على النحو التالي:


 var CHANNEL_END_TYPE = '@@redux-saga/CHANNEL_END'; var END = { type: CHANNEL_END_TYPE }; var isEnd = function isEnd(a) { return a && a.type === CHANNEL_END_TYPE; }; 

وفي eventChannel شفرة المصدر نرى النص التالي


 function eventChannel(subscribe) { … if (isEnd(input)) { close(); return; } ... } 

ما هو العازلة؟


من الجدير بالملاحظة ، نظرًا لأن كل قناة لديها مخزن مؤقت أساسي ، ومعها ، يتم تشكيل قائمة انتظار للمعالجة.


مثال على إنشاء مخزن مؤقت:


 import { buffers } from 'redux-saga' const buffer = buffers.sliding(5); 

buffers هي مثيل لمصنع لإنشاء مخازن مؤقتة مع استراتيجيات مختلفة.


فقط 5 إستراتيجيات وطرق تتوافق معها:


  • buffers.none() - لا يوجد تخزين مؤقت ، سيتم فقد الرسائل الجديدة إذا لم يكن هناك buffers.none() ؛
  • buffers.fixed(limit) - سيتم تخزين الرسائل الجديدة إلى الحد الأقصى. سيؤدي خطأ تجاوز السعة إلى استثناء. الحد الافتراضي هو 10 ؛
  • buffers.expanding(initialSize) - مثل ثابت ، ولكن الفائض سيؤدي إلى توسيع المخزن المؤقت بشكل حيوي ؛
  • buffers.dropping(limit) هو نفسه ثابت ، لكن تجاوز السعة buffers.dropping(limit) الرسائل بصمت ؛
  • buffers.sliding(limit) هو نفسه ثابت ، لكن الفائض سيضيف رسالة جديدة إلى النهاية ويحذف أقدم رسالة في المخزن المؤقت.

بدلا من اغلاق


لذلك ، درسنا لماذا اخترعت آلية القناة ، وفي ما هي المهام العملية المستخدمة.


آمل بعد قراءة الفكرة العامة وأصبح العالم أسهل قليلاً.

Source: https://habr.com/ru/post/ar432070/


All Articles