جافاسكريبت - إدارة تبعية بيانات المتجر في React/Flux


لدي تطبيق ويب تم تطويره باستخدام بنية فلوكس الخاصة بفيسبوك. تحتوي الصفحة على عرضين: يعرض أحدهما قائمة بعناصر المهام (TODO). ويعرض العرض الثاني مجموعة عشوائية من عناصر المهام (TODO).

هناك بوضوح شأنان يجب على المتاجر إدارتهما. الأول هو قائمة مهام TODO المتاحة. الثاني هو قائمة بعناصر TODO المختارة عشوائيًا.

لذلك لدي TODOStore، الذي يهتم فقط بإدارة عناصر TODO المتاحة. لديه إجراءات لـ loadTODOs، addTODO، deleteTODO، editTODO. عند بدء التشغيل، هذا المتجر لا يقوم بتحميل جميع عناصر TODO. أريد منه استرجاع قائمة عناصر TODO من قاعدة البيانات فقط عند الضرورة.

المتجر الثاني هو RandomTODOListStore. مسؤوليته هي إدارة عناصر المهام (TODO) المختارة عشوائيًا. يبدو لي أن RandomTODOListStore يجب أن يصل إلى عناصر المهام (TODO) عبر TODOStore، باستخدام TODOStore.getTODOItems().

function RandomTODOListStore() {
   var $randomTODOs = [];

   dispatcher.register(function(payload) {
        var action = payload.action;

        switch (action.actionType) {
            case Constants.LOAD_RANDOM_TODO:
                loadRandomTODO();
                break;
        }
    });

    function loadRandomTODO() {
        $randomTODOs = selectRandom(TODOStore.getTODOList());
        emit("change");
    }
}

المشكلة في هذا هي أنه، كما ذُكر سابقًا، لا يقوم TODOStore بتحميل عناصر TODO عند بدء التشغيل.

السؤال هو: "كيف يضمن RandomTODOListStore أن TODOStore قد استرجع بالفعل عناصر TODO؟".

الإجابة رقم 1

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

الواجهة مختلفة قليلاً، لأن Reflux لا يعتمد على الثوابت النصية لتمييز الإجراءات، لذا إليك مثالاً.

var TodoActions = Reflux.createActions(['load']);

var todoStore = Reflux.createStore({
    init: function() {
        // Listen to the load action
        this.listenTo(TodoActions.load, this.loadActions);
    },
    loadActions: functions() {
        var loadedActions = [];
        // load your actions into loadedActions
        // and do then the following inside the ajax 
        // callback when it is done:
        this.trigger(loadedActions);
    }
});

var randomTodoStore = Reflux.createStore({
    init: function() {
        // You may listen to stores as well
        this.listenTo(todoStore, onLoadedActions);
    },
    onLoadedActions: function(loadedActions) {
        // loaded actions will be passed in from the
        // dotoStores change event trigger

        // you may do your select random from loaded 
        // actions list   
    }
});

// Invoke the action
TodoActions.load();

آمل أن يكون هذا منطقيًا.

الإجابة رقم 2

أعتقد أن هذا هو السبب في أن بنية فلوكس تذكر الحاجة إلى مزامنة المتاجر باستخدام طريقة waitFor المذكورة هنا

إذا كنت تريد مزامنة متاجرك، فيجب أن يبدو متجر RandomTODOListStore الخاص بك على الأرجح كالتالي:

case Constants.LOAD_RANDOM_TODO:
  Dispatcher.waitFor([TodoStore.dispatcherIndex],this.loadRandomTODO);
  break; 

ثم على TodoStore الخاص بك، يمكنك التفاعل مع Constants.LOAD_RANDOM_TODO وتحميل قائمة المهام إذا لم يتم تحميلها بعد.

ومع ذلك أعتقد أن هذا معقد أكثر من اللازم، ومن المحتمل ألا يجب عليك إنشاء متجر آخر لمهام عشوائية حيث أن هذا المتجر سيقوم (على ما أظن) دائمًا بالتفويض إلى متجر المهام الحقيقي. فقط استخدم TodoStore.getRandom() بدلًا من ذلك

تعديل:

نعم، لا يحتاج TodoStore إلى معرفة كيفية استخدامه. لذلك عندما تريد الحصول على مهمة عشوائية، يمكنك على الأرجح استخدام نفس الحدث الذي تستخدمه، مثل Constants.LOAD_TODOS ثم الحصول على مهمة عشوائية من ذلك المتجر باستخدام TodoStore.getTodos()[randomIndex]

إذا أطلق كلا المكونين الحدث في الوقت نفسه، يمكنك تجاهل الحدث الثاني

حل آخر هو أن يقوم RandomTODOListStore بالاستجابة لحدث التحميل واختيار بعض المهام من المخزن الرئيسي لوضعها في RandomTODOListStore:

case Constants.TODOS_LOADED:
  this.randomTodos = randomSubset(TodoStore.getTodos,subsetSize);
  break; 

يمكنك أن تستلهم نفسك من مثال Async من Fluxxor: بالنسبة للبيانات غير المتزامنة، لا يتم إطلاق حدث واحد فقط بل حدثان (الأمر + النجاح/الفشل)