angular - RxJs: forkJoin() לא רץ כי הרשימה שלי של observables לא מלאה
ובכן, יש לי בעיה שאני לא יכול לפתור.
אני גולש ברשימת נתונים מקובץ XLSX. עבור כל שורה בקובץ נשלחות שתי בקשות לשרת:
- אחד כדי לשחזר את התקופה
- עוד כדי לשחזר משתמש
ארנק observable נוצר כדי לאחסן את שאר הנתונים בשורה. הוא הושלם מיד לאחר מכן. אחרת, הלולאה הייתה ממשיכה לפעול והנתונים האחרונים ברשימה היו נלקחים בחשבון ב-forkjoin().
אז אני משתמש ב-forkJoin() כדי לחכות לתוצאה של שלושת ה-observables שעדיין בתוך הלולאה. ברגע שהשלושת ה-observables הסתיימו, נשלח בקשה חדשה. וזה כאן שמעכב אותו. השאילתה החדשה מתווספת לרשימת ה-observables.
ואני רוצה להריץ את שאר הקוד שלי רק לאחר שרשימת ה-Observables שלי הושלמה על ידי שימוש ב-forkJoin() שוב, אחרי שעברתי על הנתונים מקובץ ה-XLSX. הבעיה היא שהלולאה שלי שעוברת על הקובץ מסתיימת לפני שרשימת ה-Observables שלי מכילה משהו, וה-forkJoin() השני אף פעם לא רץ.
קוד :
for(var objectives of this.XLSXObjectives) {
if(objectives.values != 0) {
// 2 requests (period and user)
var period$ = this.storePeriods.getPeriod(new Period({month: objectives.values[0].month, year: objectives.values[0].year}));
var user$ = this.storeUsers.getUser(new User({num_seller: objectives.values[0].userCode}));
// Observable (wallet)
var XLSXWalletSubject: BehaviorSubject<Wallet> = new BehaviorSubject<Wallet>(null);
var XLSXWallet$: Observable<any> = XLSXWalletSubject.asObservable();
XLSXWalletSubject.next(new Wallet({
wallet_name: objectives.values[0].walletName,
user: null,
period: null,
margin_m: 0,
value_100: objectives.values[0].ValueAt100Percent,
percentage_100_m: 0
}));
// Wait for the result of the three observables
forkJoin(period$, user$, XLSXWallet$).subscribe(
([period, user, wallet]) => {
console.warn("OK!");
wallet.period = period;
wallet.user = user;
// New request
var wallet$ = this.storeObjectives.addXLSXWallet(wallet);
// Request is added to a list of observables
this.observables$.push(wallet$);
wallet$.subscribe(w => { ... });
}
);
// Observable (wallet) complete
XLSXWalletSubject.complete();
}
}
console.warn(this.observables$); // this.observables$ = []
forkJoin(this.observables$).subscribe(results => {
console.log("It doesn't work!!!")
});
אם מישהו היה יכול למצוא פתרון שיעזור לי, תודה.
תשובה #1
אני לא בטוח ב-100% כאן, אבל אני חושב שמה שאתה צריך זה משהו בכיוון הזה:
from(this.XLSXObjectives).pipe(
filter(objectives => objectives.values != 0),
mergeMap(objectives => forkJoin(
this.storePeriods.getPeriod(new Period({month: objectives.values[0].month, year: objectives.values[0].year}),
this.storeUsers.getUser(new User({num_seller: objectives.values[0].userCode}),
of(new Wallet({
wallet_name: objectives.values[0].walletName,
user: null,
period: null,
margin_m: 0,
value_100: objectives.values[0].ValueAt100Percent,
percentage_100_m: 0
}))
)),
map(([period, user, wallet]) => ({ ...wallet, period, user})),
mergeMap(wallet => this.storeObjectives.addXLSXWallet(wallet)),
toArray()
).subscribe(results => { // handle array of results here });
- המטרות נפלטות אחת אחת
- ה-
mergeMapמנוי ל-forkJoinשל שלושת ה-Observables הפנימיים שלך (אם אתה צריך שהבקשות יטופלו אחת אחת, השתמש ב-concatMap, ואם אתה רוצה רק מספר מסוים של בקשות במקביל, הוסף ארגומנט concurrency ל-mergeMap) - הקריאה ל-
mapממלאת את האובייקטwalletשלך עםperiod: periodו-user: user - ה-
mergeMapהסופי מבצע את הבקשה הבאה באמצעות האובייקטwallet - הקריאה ל-
toArrayמחכה עד שה-Observable כולו יסתיים ומשדרת את כל הערכים שהתקבלו כ-arr
