Flux mimarisi ile bir reakt.js uygulaması oluşturuyorum ve nerede ve ne zaman sunucudan veri için bir istek yapılması gerektiğini anlamaya çalışıyorum. Bunun bir örneği var mı? (TODO uygulaması değil!)
Flux mimarisi ile bir reakt.js uygulaması oluşturuyorum ve nerede ve ne zaman sunucudan veri için bir istek yapılması gerektiğini anlamaya çalışıyorum. Bunun bir örneği var mı? (TODO uygulaması değil!)
Yanıtlar:
Ben eylem yaratıcıları zaman uyumsuz yazma işlemleri ve mağazada zaman uyumsuz okuma işlemleri koymak büyük bir savunucusuyum. Amaç, mağaza durumu değişiklik kodunu tamamen eşzamanlı eylem işleyicilerinde tutmaktır; bu onları akıl yürütmeyi ve ünite testini kolaylaştırır. Aynı uç noktaya (örneğin, çift okuma) aynı anda birden fazla isteği önlemek için, gerçek istek işlemeyi birden fazla isteği önlemek için vaatler kullanan ayrı bir modüle taşıyacağım; Örneğin:
class MyResourceDAO {
get(id) {
if (!this.promises[id]) {
this.promises[id] = new Promise((resolve, reject) => {
// ajax handling here...
});
}
return this.promises[id];
}
}
Mağazadaki okumalar eşzamansız işlevler içeriyor olsa da, mağazaların kendilerini eşzamansız işleyicilerde güncellemedikleri, ancak bir eylemi tetiklediği ve yalnızca yanıt geldiğinde bir eylemi tetiklediği önemli bir uyarı vardır . Bu eylemin işleyicileri gerçek durum değişikliğini yapar.
Örneğin, bir bileşen şunları yapabilir:
getInitialState() {
return { data: myStore.getSomeData(this.props.id) };
}
Mağazanın belki de böyle bir yöntem uygulanmış olması gerekir:
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
inşaattan sonra mağazalara enjekte edilir, bu nedenle başlatma yönteminde eylem almanın harika bir yolu yoktur. Yahoo'nun izomorofik akı kütüphanelerinden bazı iyi fikirler bulabilirsiniz; Bu Fluxxor v2'nin daha iyi desteklemesi gereken bir şey. Bu konuda daha fazla sohbet etmek isterseniz bana e-posta göndermekten çekinmeyin.
data: result
olmalı data : data
, değil mi? yok result
. veri parametresini faydalı yüke ya da buna benzer bir şekilde yeniden adlandırmak daha iyi olabilir.
Fluxxor sahip bir örnek , bir API ile uyumsuz iletişim.
Bu blog yayını bunun hakkında konuşuyor ve React'in blogunda yer aldı.
Bunu, arka uçla ön uç yazılım senkronizasyonu hala bir acı olduğu için henüz net olarak cevaplanmayan çok önemli ve zor bir soru olarak görüyorum.
JSX bileşenlerinde API istekleri yapılmalı mı? Mağazalar? Başka yer?
Mağazalarda isteklerin gerçekleştirilmesi, 2 mağaza belirli bir işlem için aynı verilere ihtiyaç duyarsa, 2 benzer istekte bulunacakları anlamına gelir (mağazalar arasında gerçekten sevmediğim bağımlılıklar getirmedikçe )
Benim durumumda, Q sözlerini eylem yükü olarak koymak için çok kullanışlı buldum çünkü:
Ajax kötüdür
Sanırım Ajax yakın gelecekte gittikçe daha az kullanılacak, çünkü akıl yürütmek çok zor. Doğru yol? Cihazları dağıtılmış sistemin bir parçası olarak düşünürsek, bu fikre ilk kez nereden geldiğimi bilmiyorum (belki bu ilham verici Chris Granger videosunda ).
Bunu düşün. Şimdi ölçeklenebilirlik için depolama motorları olarak nihai tutarlılığa sahip dağıtılmış sistemler kullanıyoruz (çünkü CAP teoremini yenemeyiz ve çoğu zaman kullanılabilir olmak istiyoruz). Bu sistemler birbirlerini yoklayarak senkronize etmezler (belki konsensüs işlemleri hariç?), Aksine dağıtılmış sistemin tüm üyelerini nihayetinde tutarlı hale getirmek için CRDT ve olay günlükleri gibi yapıları kullanırlar (üyeler aynı verilere, yeterli süre verilecek) .
Şimdi bir mobil cihaz veya tarayıcı hakkında düşünün. Ağ gecikmesi ve ağ bölümlendirmesinden muzdarip olabilecek yalnızca dağıtılmış sistemin bir üyesidir. (yani akıllı telefonunuzu metroda kullanıyorsunuz)
Ağ bölümü ve ağ hızına toleranslı veritabanları oluşturabilirsek (yani yalıtılmış bir düğüme yazma işlemleri gerçekleştirebiliriz), büyük olasılıkla bu kavramlardan esinlenerek çevrimdışı modun desteklediği iyi çalışan ön uç yazılımları (mobil veya masaüstü) oluşturabiliriz olmadan app kutusunun kullanılamaz özellikleri.
Veri tabanlarının, ön uç uygulamalarımızı mimarlık için nasıl çalıştığına gerçekten ilham vermemiz gerektiğini düşünüyorum. Dikkat edilmesi gereken bir şey, bu uygulamaların birbirlerine veri göndermek için POST ve PUT ve GET ajax istekleri gerçekleştirmemesi, ancak sonuç tutarlılığını sağlamak için olay günlüklerini ve CRDT'yi kullanmasıdır.
Öyleyse neden bunu ön uçta yapmıyorsunuz? Arka ucun bu yönde ilerlediğine dikkat edin, Kafka gibi araçlar büyük oyuncular tarafından kitlesel olarak benimsendi. Bu bir şekilde Olay Sağlama / CQRS / DDD ile de ilgilidir.
Kendinizi ikna etmek için Kafka yazarlarından bu harika makalelere göz atın:
Belki sunucuya komutlar göndererek ve Ajax isteklerini tetiklemek yerine bir sunucu olayları akışı (örnek için websockets aracılığıyla) alarak başlayabiliriz.
Ajax istekleri konusunda hiç bu kadar rahat olmamıştım. Biz tepki olarak geliştiriciler fonksiyonel programcı olma eğilimindedir. Bence gerçek hakikati aslında sunucu veritabanındayken ve "yerel" hakikat kaynağınız zaten güncel olmayabilirken, ön uç uygulamanızın "gerçek kaynağınız" olması gereken yerel veriler hakkında akıl yürütmenin zor olduğunu düşünüyorum aldığınızda ve bazı topallama Yenile düğmesine basmadıkça asla gerçek doğruluk değerinin kaynağına yaklaşmayacaktır ... Bu mühendislik mi?
Ancak, bazı açık nedenlerle böyle bir şey tasarlamak hala biraz zor:
this.dispatch("LOAD_DATA", {dataPromise: yourPromiseHere});
İşlem yaratıcıları veya mağazalarda veri arayabilirsiniz. Önemli olan yanıtı doğrudan ele almak değil, hata / başarı geri aramasında bir eylem oluşturmaktır. Yanıtın doğrudan mağazada ele alınması daha kırılgan bir tasarıma yol açar.
Fluxxor ajax örneğindeki Binary Muse örneğini kullanıyorum . İşte aynı yaklaşımı kullanan çok basit örneğim.
Basit bir ürün deposu bazı ürün eylemleri ve tüm ürün deposunda yapılan değişikliklere yanıt veren alt bileşenleri olan denetleyici görünümü bileşeni var . Örneğin , ürün kaydırma çubuğu , ürün listesi ve ürün arama bileşenleri.
Sahte Ürün İstemcisi
İşte gerçek bir son nokta dönen ürünleri çağırmak için değiştirebileceğiniz sahte müşteri.
var ProductClient = {
load: function(success, failure) {
setTimeout(function() {
var ITEMS = require('../data/product-data.js');
success(ITEMS);
}, 1000);
}
};
module.exports = ProductClient;
Ürün Mağazası
İşte Ürün Mağazası, açıkçası bu çok minimal bir mağaza.
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;
Şimdi AJAX isteğinde bulunan ve başarıya ulaşan ürün eylemleri, ürünleri mağazaya döndüren LOAD_PRODUCTS_SUCCESS eylemini başlatır.
Ürün İşlemleri
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;
Yani this.getFlux().actions.productActions.loadProducts()
bu mağazayı dinleyen herhangi bir bileşenden çağrı yapmak ürünleri yükleyecektir.
Yine de addProduct(id)
removeProduct(id)
, aynı modeli izleyerek vb ... gibi kullanıcı etkileşimlerine yanıt verecek farklı eylemler olduğunu hayal edebilirsiniz .
Umarım bu örnek biraz yardımcı olur, çünkü bunu uygulamak için biraz zor buldum, ancak kesinlikle mağazalarımı% 100 senkronize tutmaya yardımcı oldu.
Burada ilgili bir soruyu cevapladım: İç içe geçmiş api çağrılarını akı içinde nasıl ele alabilirim?
Eylemlerin, değişikliğe neden olan şeyler olması gerekmez. Dış dünyada bir değişikliğin uygulanmasını bildiren bir gazete gibi olmaları gerekiyor ve daha sonra uygulama bu haberlere yanıt veriyor. Mağazalar kendi içlerinde değişikliklere neden oluyor. Eylemler sadece onları bilgilendirir.
Flux'un yaratıcısı Bill Fisher https://stackoverflow.com/a/26581808/4258088
Temel olarak yapmanız gereken şey, eylemlere hangi verilere ihtiyacınız olduğunu belirtmektir. Mağaza işlem tarafından bilgilendirilirse, bazı verileri alması gerekip gerekmediğine karar vermelidir.
Mağaza, gerekli tüm verilerin toplanmasından / getirilmesinden sorumlu olmalıdır. Ancak, mağaza verileri istediğinde ve yanıtı aldıktan sonra, yanıtın doğrudan işlenmesi / kaydedilmesine karşılık, getirilen verilerle bir eylemin kendisini tetiklemesi gerektiğini belirtmek önemlidir.
Mağazalar şöyle görünebilir:
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
}
}
İşte benim almam: http://www.thedreaming.org/2015/03/14/react-ajax/
Umarım yardımcı olur. :)