Redux: البرمجيات الوسيطة معطلة

تم إنشاؤها على ٦ يونيو ٢٠١٨  ·  3تعليقات  ·  مصدر: reduxjs/redux

حشرة

تم كسر نمط برمجي وسيط مهم. معظم حلول البرمجيات الوسيطة IMO تلخص مخاوفها وهي مستقلة عن وجود برمجيات وسيطة أخرى. تم إجراء تغيير مؤخرًا لكسر نمط تسبب فقط في مشكلة ثانوية لمجموعة فرعية معينة من البرامج الوسيطة: تلك التي تظهر سلوكًا مختلفًا عند التفاعل مع البرامج الوسيطة الأخرى أثناء مسار التهيئة applyMiddleware .

وهنا بعض الأمثلة:

// Make state aware of browser media queries
const mediaQueries = (mediaQueries = defaultMediaQueries): Middleware => store => {
  if (typeof window !== 'undefined') {
    const reverseMap = createReverseMap(mediaQueries)

    const handleMediaChange = ({media, matches}: MediaChangedActionPayload) =>
      store.dispatch(mediaChanged(reverseMap[media], matches))

    const addMatchListener = (media: string) => {
      const match = window.matchMedia(media)
      match.addListener(handleMediaChange)
      return match.matches
    }

    values(mediaQueries).forEach(media => 
      handleMediaChange({media, matches: addMatchListener(media)}))
  }

  return next => (action: any) => next(action)
}

مثال آخر:

// Make state aware of user adblockers
const adBlockDetection: Middleware = store => {
  if (typeof document !== 'undefined' && !document.getElementById('XMpADSwgbPUC')) {
    store.dispatch({type: AD_BLOCKER_DETECTED, payload: true})
  }
  return next => (action: any) => next(action)
}

مثال آخر:

// Make state aware of socket connectivity and allow synchronisation of actions
const socketMiddleware = ({actionCreator, url, dataSync}) => store => {
  const socket = new WebSocket(url.replace(/(http|https)/, 'ws'))

  socket.addEventListener('message', ({data}) => {
    store.dispatch(JSON.parse(data))
  })

  socket.addEventListener('open', () => {
    socket.send(syncCreator(CONNECT_TO_DOMAIN, store.getState(), null, socket))
    store.dispatch(actionCreator({connected: true}))
  })

  socket.addEventListener('close', reason => {
    store.dispatch(actionCreator({connected: false}))
  })

  return next => action => {
    if (dataSync.hasOwnProperty(action.type)) {
      socket.send(syncCreator(action.type, store.getState(), action.payload, socket))
    }
    return next(action)
  }
}

ما هو السلوك الحالي؟

تم طرح الخطأ التالي أثناء applyMiddleware ، بشكل أساسي كسر التطبيق:

Uncaught Error: Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch

إعادة هيكلة البرمجيات الوسيطة أعلاه التي سيتم إغلاقها بواسطة الوظيفة next => (كما هو موضح أدناه) لا تحدث فرقًا (ولكن من الواضح أنها ليست حلاً قابلاً للتطبيق أيضًا).

// Still broken:
const mediaQueries = (mediaQueries = defaultMediaQueries): Middleware => store => next => {
  // ...middlewareCodeGoesHere...
  return (action: any) => next(action)
}

ما هو السلوك المتوقع؟

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

ما هي إصدارات Redux والمتصفح ونظام التشغيل المتأثران بهذه المشكلة؟

عملت حتى هذا PR .

التعليق الأكثر فائدة

markerikson نعم لقد رأيت هذه المشكلة. المشكلة الرئيسية التي "يحلها" التصميم الجديد هي:

وهنا تكمن المشكلة: يتم تنشيط هذا المستمع عند store.dispatch يستدعي

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

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

البقاء مع 3.x ليس خيارًا بالنسبة لنا لسوء الحظ ، لأننا نستخدم Typescript ، و 4.x فقط لديه الكتابة الصحيحة ، وبشكل عام ، نفضل ألا نتعثر مع إصدار قديم من جزء أساسي من منطق التطبيق حتى لو لم تكن الكتابة مشكلة.

وفي رأيي ، حتى رسالة الخطأ نفسها تلمح إلى مدى عدم أهميتها حقًا: "المشكلة" هي أن Other middleware would not be applied to this dispatch ، والذي نادرًا ما يكون مطلوبًا في الواقع ، وحتى الآن ، كان مجرد مشكلة لواحد معين حالة الاستخدام ، حيث تعتمد البرامج الوسيطة للتحليلات على الإجراءات المرسلة من جهاز التوجيه.

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

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

هذه فوضى حقيقية ، ومن الواضح أن "العلاج" أسوأ بكثير من "المرض" في هذه الحالة.

ال 3 كومينتر

تم تغيير عملية تهيئة البرنامج الوسيط بشكل صريح في 4.0 في العلاقات العامة التي قمت بربطها. كان هذا قرار تصميم متعمدًا ، ويهدف إلى حل رقم 1240.

لست متأكدًا من أن لدي اقتراحًا فوريًا لحالة الاستخدام الخاصة بك ، بخلاف محاولة تغيير منطق البرنامج الوسيط الخاص بك لانتظار بعض الإجراءات التي يتم إرسالها يدويًا "المخزن جاهز". يمكنك أيضًا التفكير في البقاء مع 3.x بدلاً من ذلك.

markerikson نعم لقد رأيت هذه المشكلة. المشكلة الرئيسية التي "يحلها" التصميم الجديد هي:

وهنا تكمن المشكلة: يتم تنشيط هذا المستمع عند store.dispatch يستدعي

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

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

البقاء مع 3.x ليس خيارًا بالنسبة لنا لسوء الحظ ، لأننا نستخدم Typescript ، و 4.x فقط لديه الكتابة الصحيحة ، وبشكل عام ، نفضل ألا نتعثر مع إصدار قديم من جزء أساسي من منطق التطبيق حتى لو لم تكن الكتابة مشكلة.

وفي رأيي ، حتى رسالة الخطأ نفسها تلمح إلى مدى عدم أهميتها حقًا: "المشكلة" هي أن Other middleware would not be applied to this dispatch ، والذي نادرًا ما يكون مطلوبًا في الواقع ، وحتى الآن ، كان مجرد مشكلة لواحد معين حالة الاستخدام ، حيث تعتمد البرامج الوسيطة للتحليلات على الإجراءات المرسلة من جهاز التوجيه.

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

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

هذه فوضى حقيقية ، ومن الواضح أن "العلاج" أسوأ بكثير من "المرض" في هذه الحالة.

لا يزال من الممكن جعل كل واحد من الأمثلة الخاصة بك يعمل. فقط أرسل بعد التقديم ربما في نوع ما من وظيفة setupMiddleware(store) أو مُحسِّن المتجر.

تم تقديم الخطأ عمدًا كبديل هو السماح للمستخدمين بالوصول إلى حالة متطرفة لها سبب غير واضح للغاية (ما لم تكن على دراية بالداخلية applyMiddleware ). تتخذ Redux موقفًا من منع أخطاء المستخدم كلما أمكن ذلك ، لذلك لن يختفي هذا الأمر.

قد يكون أحد البدائل نوعًا من رد الاتصال الذي يمكن للبرمجيات الوسيطة تسجيله كحدث afterApply . عندها ستضمن أنك سترسل في الوقت الصحيح ، بعد تطبيق كل شيء وبترتيب. سيكون من المثير للاهتمام التفكير.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات