angular - RxJS ოპბაზივების მასივი დამატებითი მონაცემებით შენარჩუნებისთვის
მოკლე ახსნა
როგორ უნდა პროცესდე observables-ის მასივი (მაგალითად forkJoin-ში) ისე, რომ თითოეული Observable-ისთვის გავატანო გარკვეული მონაცემები, რომლის გამოყენებაც მე მჭირდება pipe&map-ში?
const source = {animal: 'cat', fruit: 'apple', color: 'blue'}
const observables = Object.keys(source).map(key => [this.getDataFromApi(source[key]), key])
// resolve only observables[0][0], observables[0][1], observables[0][2] in magic way,
// but preserve observables[1][0], observables[1][1], observables[1][2] for future use in pipe&map
const processedObservable = forkJoin(observables).pipe( // ???
map(items => items.map(item => 'this is ' + item[0] + '(' + item[1] + ')')), // this doesn't work
map(items => items.join(', '))
)
processedObservable.subscribe(text => console.log(text)) // subscribe only for test
// expected result: this is your cat (animal), this is your apple (fruit), this is your blue (color)
სრული განმარტება
მქონდა რამდენიმე „source“ (ელემენტების მასივი ან ობიექტი). მე მჭირდება ყოველი ელემენტის მოთხოვნა API-ში, ასე რომ მივიღებ Observables-ის მასივს. შემდეგ, მსურს გავაგრძელო ყველა მიღებული მონაცემის დამუშავება, ამიტომ ვიყენებ forkJoin და ვამუშავებ მონაცემებს pipe-ში და რამდენიმე map-ში.
მე ვერ ვამუშავებ მონაცემებს პირდაპირ გამოწერაში.
აქ არის მარტივი მაგალითი:
const source = ['cat', 'apple', 'blue']
const observables = source.map(item => this.getDataFromApi(item))
const processedObservable = forkJoin(observables).pipe(
map(items => items.map(item => 'this is ' + item)),
map(items => items.join(', '))
)
processedObservable.subscribe(text => console.log(text)) // test
// result: this is your cat, this is your apple, this is your blue
მაგრამ აპის მოთხოვნებისთვის ნივთების მონაცემების გარდა, მაქვს ნივთების მეტატვირთი, რომელიც უნდა გამოვიყენო pipe და map პროცესირების დროს.
აქ არის მაგალითი წარმომადგენელი წყაროთი, მაგრამ აქ მე არ ვიყენებ ელემენტების მეტა-ინფორმაციას (რეზულტატი იგივეა როგორც ზემოთ). მე გავიგნორე მეტა-ინფორმაცია:
const source = {animal: 'cat', fruit: 'apple', color: 'blue'}
const observables = Object.keys(source).map(key => this.getDataFromApi(source[key]))
const processedObservable = forkJoin(observables).pipe(
map(items => items.map(item => 'this is ' + item)),
map(items => items.join(', '))
)
processedObservable.subscribe(text => console.log(text)) // test
// result: this is your cat, this is your apple, this is your blue
აქ არის მაგალითი წარმომადგენლობითი წყაროთი, მაგრამ აქ მე გამოვტოვე კლავიშები და API ზარები, მაგრამ მე ვამუშავებ ნივთების მეტადატას:
const source = {animal: 'cat', fruit: 'apple', color: 'blue'}
const observables = Object.keys(source).map(key => of(key))
const processedObservable = forkJoin(observables).pipe(
map(items => items.map(item => '(' + item + ')')),
map(items => items.join(', '))
)
processedObservable.subscribe(text => console.log(text)) // test
// result: (animal), (fruit), (color)
მინდა მივიღო ეს შედეგი:
// result: this is your cat (animal), this is your apple (fruit), this is your blue (color)
ზოგიერთ შემთხვევაში ასე pipe&map-ში:
map(items => items.map(item => 'this is ' + item.apiValue + '(' + item.key + ')')),
ან :
map(items => items.map(item => 'this is ' + item[0] + '(' + item[1] + ')')),
მაგრამ მე არ ვიცი როგორ გადავცე ობსერვებლებში და მეტამონაცემებში შედგენილი მასივი forkJoin-ს, ამ ობსერვებელთა მასივის ზოგიერთი მეტამონაცემებით:
const observables = Object.keys(source).map(key => [this.getDataFromApi(source[key]), key])
შეიძლება სხვაგვარ ფუნქციას გამოვიყენო, მაგალითად flatMap ან switchMap?
დამატებითი ინფორმაცია
მეთოდი getDataFromApi API-მუღლებიდან მონაცემების სიმულაციისთვის:
getDataFromApi(item) {
return of('your ' + item)
}
პასუხი #1
თქვენ უნდა დაამატოთ თქვენი პირველი map პირდაპირ იქ, სადაც ქმნით ინდივიდუალურ ობსერვაბლებს.
const source = { animal: "cat", fruit: "apple", color: "blue" };
const observables = Object.keys(source).map(key => getFromApi(source[key]).pipe(
map(item => `this is ${item} (${key})`)
));
const processedObservable = forkJoin(observables).pipe(
map(items => items.join(', '))
);
processedObservable.subscribe(console.log);
https://stackblitz.com/edit/rxjs-4x7hbv?file=index.ts
პასუხი #2
თითქმის არის მაგალითი იმისა, როგორ შეიძლება იქნეს შესრულებული:
from(Object.entries(source))
.pipe(
mergeMap(([key, value]) => getFromApi(value).pipe(
map(item => `this is ${item} (${key})`), // <= key is being closured
)),
toArray(), // <= transform stream to array
map(item => item.join()),
)
.subscribe(console.log);
ცადეთ შემდეგი დემოს გაშვება:
const { from, of } = rxjs;
const { map, switchMap, toArray } = rxjs.operators;
function getFromApi(item) {
return of('your ' + item)
}
const source = { animal: "cat", fruit: "apple", color: "blue" };
from(Object.entries(source))
.pipe(
mergeMap(([key, value]) => getFromApi(value).pipe(
map(item => `this is ${item} (${key})`), // <= key is being closured
)),
toArray(), // <= transform stream to array
map(item => item.join()),
)
.subscribe(console.log);<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>