ما هو Redux Saga؟

فبراير 15, 2025

Redux Saga هو عبارة عن مكتبة middleware لـ Redux، تساعد في إدارة المهام غير المتزامنة (side effects) في تطبيقات Redux بطريقة بسيطة وسهلة. باستخدام ميزة Generators (function*) في ES6، يسمح بكتابة أكواد غير متزامنة لكنها تبدو وكأنها أكواد متزامنة.

لا يقتصر Redux Saga على عالم JavaScript فحسب، بل يُعتبر أيضًا نمط تصميم. يُعد Saga pattern طريقة لإدارة المعاملات (transactions) الطويلة مع العديد من التأثيرات الجانبية أو المخاطر المحتملة. مع كل معاملة ناجحة، يجب أن يكون هناك counter-transaction لعكس (revert) تلك المعاملة إلى حالتها الأصلية في حالة حدوث مشكلة.

مخطط يوضح مفهوم Saga Pattern في إدارة المعاملاتمخطط يوضح مفهوم Saga Pattern في إدارة المعاملات

التأثيرات الجانبية (Side effects) هي المهام في البرمجة الدالية التي تحتاج إلى التفاعل مع العالم الخارجي، مثل استدعاء API للحصول على البيانات، أو حفظ البيانات في localStorage، أو قراءة ملفات تعريف الارتباط (cookies) من المتصفح. عادةً ما تكون هذه المهام غير متزامنة ويمكن أن تغير حالة التطبيق. يُطلب من Reducer في Redux أن يكون متزامنًا (synchronous) ونقيًا (pure)، أي أنه يعالج المنطق فقط بناءً على المدخلات ويعيد المخرجات دون التسبب في تأثيرات جانبية. لذلك، يتم استخدام Redux Saga لمعالجة التأثيرات الجانبية خارج Reducer، مما يساعد في الحفاظ على بساطة Reducer وسهولة اختباره.

دالة Generator هي نوع خاص من الدوال في JavaScript، تتميز بالقدرة على إيقاف التنفيذ مؤقتًا وإرجاع القيمة عدة مرات. تُستخدم الكلمة الأساسية yield لإيقاف التنفيذ وإرجاع القيمة. على عكس الدالة العادية التي تُنفذ وتُرجع النتيجة مرة واحدة، يمكن لدالة Generator التنفيذ، إيقاف التنفيذ مؤقتًا لإرجاع النتيجة، ثم متابعة التنفيذ من الموضع الذي توقفت عنده.

يعمل Redux Saga عن طريق الاستماع إلى actions التي يتم إرسالها (dispatch). عندما يتم إرسال action، يتحقق Redux Saga مما إذا كان هذا action هو الذي يهتم به أم لا. إذا كان الأمر كذلك، فإنه سينفذ دالة Generator المقابلة. ستقوم دالة Generator هذه بإرجاع effect objects باستخدام yield. Effect objects هي كائنات تحتوي على معلومات توجه middleware في Redux لتنفيذ أنشطة أخرى، مثل استدعاء دالة غير متزامنة أو إرسال (put) action جديد إلى store.

فلماذا نستخدم Redux Saga؟ بالمقارنة مع Redux Thunk، وهو middleware آخر يُستخدم عادةً لمعالجة التأثيرات الجانبية، يوفر Redux Saga العديد من الفوائد. غالبًا ما يؤدي Redux Thunk إلى “callback hell” عند معالجة العديد من المهام غير المتزامنة المتداخلة، مما يجعل الكود صعب القراءة والصيانة. يساعد Redux Saga، من خلال استخدام دوال Generator و effect objects، في جعل الكود أسهل في القراءة والفهم والاختبار. يسمح Redux Saga باختبار التدفقات غير المتزامنة (asynchronous flows) بسهولة ويحافظ على actions نقية (pure).

مثال على مقارنة بين Redux Thunk و Redux Saga في معالجة طلب API:

Redux Thunk:

import { API_BUTTON_CLICK, API_BUTTON_CLICK_SUCCESS, API_BUTTON_CLICK_ERROR } from './actions/consts';
import { getDataFromAPI } from './api';

const getDataStarted = () => ({ type: API_BUTTON_CLICK });
const getDataSuccess = data => ({ type: API_BUTTON_CLICK_SUCCESS, payload: data });
const getDataError = message => ({ type: API_BUTTON_CLICK_ERROR, payload: message });

const getDataFromAPI = () => {
  return dispatch => {
    dispatch(getDataStarted());
    getDataFromAPI()
      .then(data => {
        dispatch(getUserSuccess(data));
      })
      .catch(err => {
        dispatch(getDataError(err.message));
      });
  };
};

Redux Saga:

import { call, put, takeEvery } from 'redux-saga/effects';
import { API_BUTTON_CLICK, API_BUTTON_CLICK_SUCCESS, API_BUTTON_CLICK_ERROR } from './actions/consts';
import { getDataFromAPI } from './api';

export function* apiSideEffect(action) {
  try {
    const data = yield call(getDataFromAPI);
    yield put({ type: API_BUTTON_CLICK_SUCCESS, payload: data });
  } catch (e) {
    yield put({ type: API_BUTTON_CLICK_ERROR, payload: e.message });
  }
}

export function* apiSaga() {
  yield takeEvery(API_BUTTON_CLICK, apiSideEffect);
}

يساعد Redux Saga في فصل منطق معالجة التأثيرات الجانبية عن المكون (component) و Reducer، مما يجعل الكود سهل الصيانة والتوسع والاختبار. استخدام try/catch في Redux Saga يجعل معالجة الأخطاء أسهل من استخدام سلسلة الوعود (promise chain) في Redux Thunk.

Leave A Comment

تصنيفات

Recent Posts

Create your account