Reputation:
I found this code on a project while fixing a bug. This is a behaviour i cant really understand : Here is a live example on stackblitz // or find the code below
import { of } from 'rxjs'
import { delay } from 'rxjs/operators'
// CASE 1
class List {
items = new Map();
getList() {
of([{id:1, desc:'item1 desc'}, {id:2, desc:'item2 desc'}])
.pipe(delay(500))
.subscribe(
items => {
for (const item of items) {
this.items.set(item.id, item.desc)
}
}
)
return this.items;
}
}
const myList = new List()
const list1 = myList.getList()
const list2 = myList.getList()
setTimeout(() => console.log('list 1 with timeout', list1), 1000) // => List populated
setTimeout(() => console.log('list 2 with timeout', list2), 1000) // => List populated
// CASE 2
class List2 {
items = new Map()
getList() {
this.items = new Map()
of([{id:1, desc:'item1 desc'}, {id:2, desc:'item2 desc'}])
.pipe(delay(500))
.subscribe(
items => {
for (const item of items) {
this.items.set(item.id, item.desc)
}
}
)
return this.items;
}
}
const myList2 = new List2()
const list3 = myList2.getList()
const list4 = myList2.getList()
setTimeout(() => console.log('list 3 with timeout', list3), 1000) // => List NOT populated why ?
setTimeout(() => console.log('list 4 with timeout', list4), 1000) // => List populated
I just can't understand what's going on here and why the first Map display the result i'm expecting while the second Map return an empty Map ?
Thanks for the help !
PS: i know this is probably not a good rxjs usage, but just wanted to understand...
Upvotes: 1
Views: 172
Reputation: 11
This is being caused by a race condition. Your observable runs asynchronously, so your returning the list occurs before it gets populated. It's easier to see this, if you increase your delays in the observable to say 500ms. If you do, you'll see that both lists are empty in the console.log.
But because your timeouts are so short, the thread scheduler allows the code from the List class to complete, before switching back to the console thread. If I had to speculate, the second list behaves differently because the process needs additional time for the reallocation of the Map at the beginning of the function. Therefore in the second case, the scheduler switches back before the list gets populated, so you see nothing.
Upvotes: 1