मैं फ्लक्स आर्किटेक्चर के साथ एक react.js एप्लिकेशन बना रहा हूं और मैं यह पता लगाने की कोशिश कर रहा हूं कि सर्वर से डेटा के लिए अनुरोध कहां और कब किया जाना चाहिए। क्या इसके लिए कोई उदाहरण है। (TODO ऐप नहीं!)
मैं फ्लक्स आर्किटेक्चर के साथ एक react.js एप्लिकेशन बना रहा हूं और मैं यह पता लगाने की कोशिश कर रहा हूं कि सर्वर से डेटा के लिए अनुरोध कहां और कब किया जाना चाहिए। क्या इसके लिए कोई उदाहरण है। (TODO ऐप नहीं!)
जवाबों:
मैं एक्शन रचनाकारों में async लिखने के संचालन और दुकान में async रीड ऑपरेशन डालने का एक बड़ा प्रस्तावक हूँ। लक्ष्य स्टोर राज्य संशोधन कोड को पूरी तरह से सिंक्रोनस एक्शन हैंडलर में रखना है; यह उन्हें सरल और इकाई परीक्षण के लिए सरल कारण बताता है। एक ही समापन बिंदु (उदाहरण के लिए, डबल-रीडिंग) के लिए एक साथ कई अनुरोधों को रोकने के लिए, मैं वास्तविक अनुरोध प्रसंस्करण को एक अलग मॉड्यूल में स्थानांतरित करूँगा जो कई अनुरोधों को रोकने के लिए वादों का उपयोग करता है; उदाहरण के लिए:
class MyResourceDAO {
get(id) {
if (!this.promises[id]) {
this.promises[id] = new Promise((resolve, reject) => {
// ajax handling here...
});
}
return this.promises[id];
}
}
स्टोर में पढ़ते समय अतुल्यकालिक कार्यों को शामिल किया जाता है, एक महत्वपूर्ण चेतावनी है कि स्टोर खुद को async संचालकों में अपडेट नहीं करते हैं, लेकिन इसके बजाय एक कार्रवाई को फायर करते हैं और प्रतिक्रिया आने पर केवल कार्रवाई करते हैं। इस कार्रवाई के लिए हैंडलर वास्तविक राज्य संशोधन करते हैं।
उदाहरण के लिए, एक घटक यह कर सकता है:
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
}
}
flux
से निर्माण के बाद दुकानों में इंजेक्ट किया जाता है, इसलिए प्रारंभिक विधि में कार्रवाई करने का कोई शानदार तरीका नहीं है। आपको याहू के आइसोमोर्फिक फ्लक्स लिबास से कुछ अच्छे विचार मिल सकते हैं; यह कुछ है Fluxxor v2 बेहतर समर्थन करना चाहिए। यदि आप इस बारे में अधिक चैट करना चाहते हैं, तो मुझे ईमेल करें।
data: result
होना चाहिए data : data
, है ना? नहीं है result
। शायद पेलोड या ऐसा कुछ करने के लिए डेटा परम का नाम बदलने के लिए बेहतर है।
Fluxxor में API के साथ async संचार का एक उदाहरण है।
इस ब्लॉग पोस्ट में इसके बारे में बातचीत है और इसे रिएक्ट के ब्लॉग पर चित्रित किया गया है।
मुझे यह एक बहुत ही महत्वपूर्ण और कठिन प्रश्न है जिसका स्पष्ट रूप से अभी तक उत्तर नहीं दिया गया है, क्योंकि बैकएंड के साथ फ्रंटेंड सॉफ्टवेयर सिंक्रोनाइज़ेशन अभी भी एक दर्द है।
क्या JSX घटकों में API अनुरोध किया जाना चाहिए? स्टोर? अन्य जगह?
दुकानों में अनुरोध करने का मतलब है कि अगर 2 दुकानों को किसी दिए गए कार्य के लिए समान डेटा की आवश्यकता है, तो वे 2 समान अनुरोध जारी करेंगे (जब तक कि आप दुकानों के बीच निर्भरता का परिचय नहीं देते हैं, जो मुझे पसंद नहीं है )
मेरे मामले में, मैंने क्यू वादों को कार्यों के पेलोड के रूप में रखना बहुत आसान पाया है क्योंकि:
Ajax EVIL है
मुझे लगता है कि निकट भविष्य में अजाक्स कम और कम उपयोग किया जाएगा क्योंकि इसके बारे में तर्क करना बहुत कठिन है। सही तरीका? वितरित प्रणाली के हिस्से के रूप में उपकरणों को ध्यान में रखते हुए मुझे नहीं पता कि मैं पहली बार इस विचार में आया था (शायद इस प्रेरणादायक क्रिस ग्रेंजर वीडियो में )।
इसके बारे में सोचो। स्केलेबिलिटी के लिए अब हम स्टोरेज इंजन के रूप में अंतिम स्थिरता के साथ वितरित सिस्टम का उपयोग करते हैं (क्योंकि हम कैप प्रमेय को हरा नहीं सकते हैं और अक्सर हम उपलब्ध होना चाहते हैं)। ये प्रणालियां एक-दूसरे को मतदान करने के माध्यम से सिंक नहीं करती हैं (शायद सर्वसम्मति के संचालन को छोड़कर?) बल्कि वितरित प्रणाली के सभी सदस्यों को सुसंगत बनाने के लिए CRDT और इवेंट लॉग जैसी संरचनाओं का उपयोग करें (सदस्य एक ही डेटा में कनवर्ट करेंगे, पर्याप्त समय दिया गया) ।
अब सोचें कि मोबाइल डिवाइस या ब्राउज़र क्या है। यह वितरित प्रणाली का सिर्फ एक सदस्य है जो नेटवर्क विलंबता और नेटवर्क विभाजन का शिकार हो सकता है। (यानी आप मेट्रो पर अपने स्मार्टफोन का इस्तेमाल कर रहे हैं)
यदि हम नेटवर्क विभाजन और नेटवर्क स्पीड टॉलरेंट डेटाबेस बना सकते हैं (मेरा मतलब है कि हम अभी भी एक अलग नोड के लिए ऑपरेशन लिख सकते हैं), हम शायद इन अवधारणाओं से प्रेरित फ्रंटएंड सॉफ्टवेयर्स (मोबाइल या डेस्कटॉप) बना सकते हैं, जो ऑफ़लाइन मोड के साथ अच्छी तरह से काम करते हैं। एप्लिकेशन के बिना बॉक्स में अनुपलब्धता है।
मुझे लगता है कि हमें वास्तव में खुद को प्रेरित करना चाहिए कि डेटाबेस हमारे सीमांत अनुप्रयोगों को कैसे काम कर रहे हैं। ध्यान देने वाली एक बात यह है कि ये ऐप एक-दूसरे को डेटा भेजने के लिए POST और PUT और GET ajax अनुरोध नहीं करते हैं, बल्कि अंतिम स्थिरता सुनिश्चित करने के लिए इवेंट लॉग और CRDT का उपयोग करते हैं।
तो ऐसा क्यों नहीं किया गया? ध्यान दें कि बैकेंड पहले से ही उस दिशा में आगे बढ़ रहा है, जिसमें काफ्का जैसे उपकरण बड़े खिलाड़ियों द्वारा बड़े पैमाने पर अपनाए गए हैं। यह किसी तरह इवेंट सोर्सिंग / CQRS / DDD से भी संबंधित है।
खुद को समझाने के लिए काफ्का लेखकों के इन भयानक लेखों की जाँच करें:
हो सकता है कि हम सर्वर को कमांड भेजकर शुरू कर सकते हैं, और अजाक्स अनुरोधों को हटाने के बजाय सर्वर घटनाओं की एक धारा प्राप्त कर सकते हैं (छूट के लिए वेबस्कैट के माध्यम से)।
मैं अजाक्स अनुरोध के साथ बहुत सहज नहीं था। जैसा कि हम अभिकर्मक विकसित करते हैं वे कार्यात्मक प्रोग्रामर होते हैं। मुझे लगता है कि स्थानीय डेटा के बारे में तर्क करना मुश्किल है जो आपके सामने वाले एप्लिकेशन के "सत्य का स्रोत" माना जाता है, जबकि सच्चाई का वास्तविक स्रोत वास्तव में सर्वर डेटाबेस पर है, और आपका "स्थानीय" स्रोत सत्य का पुराना हो सकता है जब आप इसे प्राप्त करते हैं, और सत्य मूल्य के वास्तविक स्रोत तक कभी नहीं जुटाएंगे जब तक कि आप कुछ लंगड़ा ताज़ा नहीं करते हैं ... क्या यह इंजीनियरिंग है?
हालाँकि कुछ स्पष्ट कारणों के लिए इस तरह की चीज़ को डिज़ाइन करना थोड़ा कठिन है:
this.dispatch("LOAD_DATA", {dataPromise: yourPromiseHere});
आप एक्शन क्रिएटर्स या स्टोर्स में डेटा के लिए कॉल कर सकते हैं। महत्वपूर्ण बात यह है कि प्रतिक्रिया को सीधे संभालना नहीं है, लेकिन त्रुटि / सफलता कॉलबैक में एक कार्रवाई बनाने के लिए। सीधे दुकान में प्रतिक्रिया को संभालने से अधिक भंगुर डिजाइन होता है।
मैं फ्लक्सएक्सोर अजाक्स उदाहरण से बाइनरी म्यूज़िक के उदाहरण का उपयोग कर रहा हूं । यहाँ एक ही दृष्टिकोण का उपयोग करके मेरा बहुत सरल उदाहरण है।
मेरे पास एक सरल उत्पाद स्टोर कुछ उत्पाद क्रियाएं और नियंत्रक-दृश्य घटक है जिसमें उप-घटक हैं जो सभी उत्पाद स्टोर में किए गए परिवर्तनों का जवाब देते हैं । उदाहरण के लिए उत्पाद-स्लाइडर , उत्पाद-सूची और उत्पाद-खोज घटक।
नकली उत्पाद ग्राहक
यहाँ नकली ग्राहक है जिसे आप एक वास्तविक समापन बिंदु लौटने वाले उत्पादों को कॉल करने के लिए स्थानापन्न कर सकते हैं।
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_PRODUCS_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% तुल्यकालिक रखने में मदद की।
मैंने यहां एक संबंधित प्रश्न का उत्तर दिया: फ्लक्स में नेस्टेड एप कॉल को कैसे संभालना है
क्रियाएँ ऐसी चीज़ें नहीं हैं जो बदलाव का कारण बनें। उन्हें एक अखबार की तरह माना जाता है जो बाहरी दुनिया में बदलाव के आवेदन की सूचना देता है, और फिर आवेदन उस समाचार पर प्रतिक्रिया देता है। स्टोर अपने आप में बदलाव का कारण बनते हैं। क्रियाएँ सिर्फ उन्हें सूचित करती हैं।
बिल फिशर, फ्लक्स के निर्माता https://stackoverflow.com/a/26581808/4258088
आपको मूल रूप से क्या करना चाहिए, यह उन क्रियाओं के माध्यम से बताया गया है कि आपको किस डेटा की आवश्यकता है। यदि स्टोर को कार्रवाई से सूचित किया जाता है, तो यह तय करना चाहिए कि क्या उसे कुछ डेटा प्राप्त करना है।
स्टोर सभी आवश्यक डेटा को संचित / लाने के लिए जिम्मेदार होना चाहिए। हालांकि, यह नोट करना महत्वपूर्ण है कि स्टोर द्वारा डेटा का अनुरोध करने और प्रतिक्रिया प्राप्त करने के बाद, उसे सीधे प्राप्त प्रतिक्रिया को सहेजने / स्टोर करने के विरोध में, प्राप्त किए गए डेटा के साथ एक कार्रवाई को ट्रिगर करना चाहिए।
एक स्टोर कुछ इस तरह दिख सकता है:
class DataStore {
constructor() {
this.data = [];
this.bindListeners({
handleDataNeeded: Action.DATA_NEEDED,
handleNewData: Action.NEW_DATA
});
}
handleDataNeeded(id) {
if(neededDataNotThereYet){
api.data.fetch(id, (err, res) => {
//Code
if(success){
Action.newData(payLoad);
}
}
}
}
handleNewData(data) {
//code that saves data and emit change
}
}
यहाँ मेरा इस पर है: http://www.thedreaming.org/2015/03/14/react-ajax/
उम्मीद है की वो मदद करदे। :)