javascript برنامج - أين يجب أن يتم طلب ajax في تطبيق Flux؟




معنى definition (6)

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


Answers

وإليك نصيبي على هذا: http://www.thedreaming.org/2015/03/14/react-ajax/

امل ان يساعد. :)


لدى Fluxxor مثال على التواصل غير المتزامن مع API.

تتحدث هذه المدونة عن هذا الموضوع وقد ظهرت في مدونة React.

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

هل يجب إجراء طلبات واجهة برمجة التطبيقات في مكونات JSX؟ المخازن؟ مكان آخر؟

أداء الطلبات في المتاجر يعني أنه إذا احتاج متجرين إلى نفس البيانات لإجراء معين ، فسيصدران متطلبين متشابهين (إلا إذا قمت بتقديم التبعيات بين المتاجر ، والتي لا أحبها حقًا )

في حالتي ، لقد وجدت هذا مفيدًا جدًا لوضع وعود Q كحملة من الإجراءات بسبب:

  • لا تحتاج إجراءاتي إلى أن تكون قابلة للتسلسل (لا احتفظ بسجل الأحداث ، ولا أحتاج إلى ميزة إعادة تشغيل الحدث في مصادر الأحداث)
  • إنه يزيل الحاجة إلى اتخاذ إجراءات / أحداث مختلفة (الطلب المطلق / الطلب مكتمل / فشل الطلب) ويجب أن يضاهيها باستخدام معرفات الارتباط عندما يمكن إطلاق الطلبات المتزامنة.
  • يسمح لـ مخزن متعددة للاستماع إلى إكمال نفس الطلب ، دون إدخال أي تبعية بين المخازن (ومع ذلك قد يكون من الأفضل إدخال طبقة التخزين المؤقت؟)

اجاكس هو الشر

أعتقد أن أياكس سوف يستخدم أقل وأقل في المستقبل القريب لأنه من الصعب جدا التفكير فيه. الطريق الصحيح؟ بالنظر إلى الأجهزة كجزء من النظام الموزع ، لا أعرف من أين صادفت هذه الفكرة لأول مرة (ربما في هذا الفيديو الملهم كريس غرانغر ).

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

الآن فكر في ما هو جهاز محمول أو متصفح. إنه مجرد عضو في النظام الموزع الذي قد يعاني من تأخر الشبكة وتقسيم الشبكة. (أي أنك تستخدم هاتفك الذكي في مترو الأنفاق)

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

أعتقد أننا يجب أن نلهم أنفسنا بالفعل كيف تعمل قواعد البيانات على تصميم تطبيقات الواجهة. شيء واحد يجب أن نلاحظه هو أن هذه التطبيقات لا تنفذ طلبات POST و PUT و GET ajax لإرسال البيانات إلى بعضها البعض ، بل تستخدم سجلات الأحداث و CRDT لضمان الاتساق في النهاية.

فلماذا لا نفعل ذلك على الواجهة؟ لاحظ أن الواجهة الخلفية تتحرك بالفعل في هذا الاتجاه ، باستخدام أدوات مثل كافكا التي تم تبنيها بشكل كبير من قبل اللاعبين الكبار. يرتبط هذا بطريقة ما بـ Event Sourcing / CQRS / DDD أيضًا.

تحقق من هذه المقالات الرائعة من مؤلفي كافكا لإقناع نفسك:

ربما يمكننا البدء عن طريق إرسال الأوامر إلى الخادم ، وتلقي مجموعة من أحداث الخادم (من خلال websockets for exemple) ، بدلاً من إطلاق طلبات Ajax.

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

ومع ذلك ، لا يزال من الصعب تصميم شيء من هذا القبيل لبعض الأسباب الواضحة:

  • يمتلك عميل الجوال / المتصفح الخاص بك موارد محدودة ولا يمكنه بالضرورة تخزين كافة البيانات محليًا (وبالتالي يتطلب أحيانًا الاقتراع مع محتوى ثقيل لطلب AJAX)
  • يجب أن لا يرى عميلك جميع بيانات النظام الموزع ، لذلك يتطلب بطريقة ما تصفية الأحداث التي يتلقاها لأسباب أمنية

لقد تم استخدام مثال Binary موسى من المثال Fluxxor اياكس . هنا مثال بسيط للغاية باستخدام نفس النهج.

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

عميل منتج مزيف

في ما يلي العميل المزيّف الذي يمكنك استبداله باستدعاء منتجات نهائية فعلية.

var ProductClient = {

  load: function(success, failure) {
    setTimeout(function() {
      var ITEMS = require('../data/product-data.js');
      success(ITEMS);
    }, 1000);
  }    
};

module.exports = ProductClient;

متجر المنتجات

هنا هو متجر المنتجات ، ومن الواضح أن هذا هو متجر صغير للغاية.

var Fluxxor = require("fluxxor");

var store = Fluxxor.createStore({

  initialize: function(options) {

    this.productItems = [];

    this.bindActions(
      constants.LOAD_PRODUCTS_SUCCESS, this.onLoadSuccess,
      constants.LOAD_PRODUCTS_FAIL, this.onLoadFail
    );
  },

  onLoadSuccess: function(data) {    
    for(var i = 0; i < data.products.length; i++){
      this.productItems.push(data.products[i]);
    }    
    this.emit("change");
  },

  onLoadFail: function(error) {
    console.log(error);    
    this.emit("change");
  },    

  getState: function() {
    return {
      productItems: this.productItems
    };
  }
});

module.exports = store;

الآن إجراءات المنتج ، والتي تجعل طلب AJAX ونجاح إطلاق النار على المنتجات LOAD_PRODUCTS_SUCCESS العودة إلى المتجر.

إجراءات المنتج

var ProductClient = require("../fake-clients/product-client");

var actions = {

  loadProducts: function() {

    ProductClient.load(function(products) {
      this.dispatch(constants.LOAD_PRODUCTS_SUCCESS, {products: products});
    }.bind(this), function(error) {
      this.dispatch(constants.LOAD_PRODUCTS_FAIL, {error: error});
    }.bind(this));
  }    

};

module.exports = actions;

لذا ، فإن استدعاء هذا this.getFlux().actions.productActions.loadProducts() من أي مكون يستمع إلى هذا المتجر يقوم بتحميل المنتجات.

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

نأمل أن هذا المثال يساعد قليلا ، كما وجدت هذا صعب قليلا لتنفيذ ، ولكن بالتأكيد ساعد في الحفاظ على متجري متزامنة 100 ٪.


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

class MyResourceDAO {
  get(id) {
    if (!this.promises[id]) {
      this.promises[id] = new Promise((resolve, reject) => {
        // ajax handling here...
      });
    } 
    return this.promises[id];
  }
}

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

على سبيل المثال ، قد يفعل المكون ما يلي:

getInitialState() {
  return { data: myStore.getSomeData(this.props.id) };
}

سيكون لدى المتجر طريقة تم تنفيذها ، ربما ، شيء من هذا القبيل:

class Store {
  getSomeData(id) {
    if (!this.cache[id]) {
      MyResurceDAO.get(id).then(this.updateFromServer);
      this.cache[id] = LOADING_TOKEN;
      // LOADING_TOKEN is a unique value of some kind
      // that the component can use to know that the
      // value is not yet available.
    }

    return this.cache[id];
  }

  updateFromServer(response) {
    fluxDispatcher.dispatch({
      type: "DATA_FROM_SERVER",
      payload: {id: response.id, data: response}
    });
  }

  // this handles the "DATA_FROM_SERVER" action
  handleDataFromServer(action) {
    this.cache[action.payload.id] = action.payload.data;
    this.emit("change"); // or whatever you do to re-render your app
  }
}

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


استخدم $.ajax() منخفض المستوى:

$.ajax({
  url: "/yourservlet",
  data: { },
  complete: function(xmlHttp) {
    // xmlHttp is a XMLHttpRquest object
    alert(xmlHttp.status);
  }
});

جرب هذا لإعادة توجيه:

if (xmlHttp.code != 200) {
  top.location.href = '/some/other/page';
}




javascript reactjs reactjs-flux