मेरे पास काफी सामान्य उपयोग का मामला है। मैं FirebaseDatabase से ऑब्जेक्ट्स की एक सरणी लोड कर रहा हूं, और फायरबेस स्टोरेज से इमेज अटैच कर रहा हूं।
FirebaseDatabase एक ऑब्जर्वेबल पर आधारित रिटर्न देता हैक्वेरी। डीबी में हर बार डेटा बदल जाएगा, ऑब्जर्वेबल एक अद्यतन क्वेरी परिणाम का उत्सर्जन करेगा। मैं परिणाम में प्रत्येक प्रविष्टि के लिए [डोमेन, ImagePromise] टपल पर मैपिंग करके स्टोरेज एप से प्रत्येक प्रविष्टि के लिए एक प्रॉमिस संलग्न करता हूं।
getDomainObj(){
return this.af.database.list(this.listRef)
.map((mps: Domain[]) =>
mps.map((mp: Domain) =>
[mp, this.getImage(mp["$key"])]));
}
दो मुद्दे:
- कुछ mps डॉन 'टी की एक छवि है।
- चूँकि चित्र firedb में नहीं हैं, aछवि परिवर्तन पर अवलोकन योग्य नहीं होगा। इसे ठीक करने के लिए, मैंने प्रत्येक इमेज अपडेट पर पुश नोट भेजने के लिए एक क्लाउड फ़ंक्शन जोड़ा (इस प्रश्न के दायरे के बाहर, यह काम करता है, इसलिए इसमें जाने की कोई आवश्यकता नहीं है)। प्रत्येक mp का अपना PubSub विषय होता है, और हम क्लाइंट में विषय की सदस्यता लेते हैं, और उन अद्यतनों का अवलोकन प्राप्त करते हैं जो हर बार किसी विशिष्ट MP के लिए एक छवि अपलोड होने पर निकल जाएंगे
मैं मैपिंग करके उन दोनों को हल करता हूं
this.mpSvc.getDomainObj()
.map((tupleArray: [Domain, Promise<string>][]) =>
tupleArray.map(([mp, imageSrcPromise]: [Domain, Promise<string>]) => {
return [mp,
Observable.fromPromise(imageSrcPromise) // get initial image
.startWith(null) // make sure that it emits at least once
.concat( // updates
this.mpSvc.signUpForPictureUpdates(mp["$key"])
.map(([id, imageSrc]: [string, string]) => imageSrc))
];
})
)
mpSvc.signUpForPictureUpdates
डोमेन का एक ऑब्जर्वेबल रिटर्न
अब अंतिम लक्ष्य का पालन करना है[डोमेन, ImageSrc] की एक सरणी, जो हर बार डोमेन ऑब्जेक्ट में से किसी एक की छवि, या किसी भी डोमेन ऑब्जेक्ट परिवर्तन या क्वेरी परिवर्तन के परिणामस्वरूप की छवि का उत्सर्जन करेगी।
पहले मैं फिर से रीमैप करता हूं, [डोमेन, ऑब्जर्वेबल] जोड़े की एक सरणी को छोड़ने के बजाय, ऑब्जर्व करने योग्य <[डोमेन, imageSrc]> की एक सरणी का उत्सर्जन करता हूं
.map((tupleArray: [Domain, Observable<string>][]) =>
tupleArray.map(([mp, imageSrcObservable]: [Domain, Observable<string>]) =>
imageSrcObservable.map((imageSrc: string) => [mp, imageSrc])))
अब मेरे पास एक सरणी का अवलोकन हैजोड़ियों का अवलोकन। मूल अवलोकन हर बार एक डोमेन या क्वेरी परिणाम बदल जाएगा, और बच्चे हर बार एक विशिष्ट डोमेन के लिए एक छवि बदल जाएगा उत्सर्जन करेंगे।
अंतिम चरण के लिए, मैं बच्चों को देखने योग्य एक ही वेधशाला में स्विच करता हूं और इसे स्विचपॉइंट करता हूं।
.switchMap((imageObservables: Observable<[Domain, string]>[]) =>
Observable.combineLatest(imageObservables)
)
परिणाम ठीक से सब्सक्राइब किया गया है (वास्तव में, यह एनजीएफ के माध्यम से कोणीय टेम्पलेट में प्रदर्शित किया गया है। async, लेकिन यह भी दायरे से बाहर है)।
दुर्भाग्य से, परिणाम अपेक्षित नहीं हैं। वास्तव में, मेरे पास क्वेरी से चार परिणाम ऑब्जेक्ट हैं, दो छवियों के साथ, और दो बिना। जो मैं देख रहा हूं वह सुसंगत नहीं है - कभी-कभी दोनों छवियां लोड होती हैं, कभी-कभी एक, और सबसे अधिक बार न तो।
विशेष रूप से, अगर मैं अंत करने के लिए एक लॉगिंग लाइन जोड़ना चाहते थे तो:
.do(x => console.log("final", x), x => console.error("finalerror", x), () => console.log("finalcomplete"));
मैं हमेशा इमेजस् आर्क में नल के साथ कम से कम एक लॉग लाइन प्राप्त करता हूं, लेकिन कभी-कभी वास्तविक इमेज्रस के साथ कभी-कभी अतिरिक्त लाइनें।
अंतिम चरण (CombLLestest) से पहले सदस्यता लेने से सभी डेटा ठीक से मिल जाते हैं
मैं क्या गलत कर रहा हूं?
संपादित करें: इसे और अधिक देखने के बाद, समस्या निश्चित रूप से है combineLatest
। मैंने बदलने की कोशिश की combineLatest
साथ में imageObservables[1].map(x=>[x])
और यह पूरी तरह से काम करता है (हालांकि केवल निश्चित रूप सेसरणी के बजाय एक मान लौटाता है। इसके अलावा, CombLatest के माध्यम से कदम रखने से मुझे कुछ बंद हो गया जो अजीब है, क्योंकि किसी भी बिंदु पर बंद करने की आवश्यकता क्या होगी?
उत्तर:
जवाब के लिए 2 № 1ठीक है, मुझे समस्या मिल गई। fromPromise
एक त्रुटि फेंक देंगे अगर वादा खारिज कर दिया। इस प्रकार, बच्चों में से एक त्रुटि "जब इसे संपादित करें getImage
didn "t को एक छवि मिलती है, जो इसका कारण बनती है combineLatest
पूरा करना।
मैंने इसे इस तरह तय किया
Observable.fromPromise(imageSrcPromise) // get initial image
.catch(() => Observable.empty()) // <-- fix
.startWith(null) // and so forth...
यही कारण है कि कभी-कभी यह ठीक से उत्सर्जित होता है, औरकभी-कभी यह "t" नहीं होता है। यदि पहले लोड की गई छवियों के साथ डोमेन ऑब्जेक्ट के लिए अनुरोध, तो वे प्रदर्शित करेंगे। यदि छवि-कम ऑब्जेक्ट पहले लौट आए, तो स्ट्रीम समाप्त हो जाएगी।