问题
I have a list of books, with IsEnable default to False. I need to check each book whether its enabled or not in onInit(). I thought of adding a rxjs map and call the getEligibleBooks() function inside the map, but how to assign the return value true or false in the IsEnable?
Books.ts
export class Book{
Name:string;
IsEnable:boolean;
}
books.component.ts
...
books = Observable.of([{"Name":"A", "IsEnable":"False"},{"Name":"B", "IsEnable":"False"}]);
...
getEligibleBooks(book){
//complex logic
return result; //true or false
}
...
ngOnInit(){
this.books.pipe(
map( book => this.getEligibleBooks(book)) // have no idea how to achieve it
).subscribe(data=>console.log(data));
}
回答1:
- As you are not actually changing the returned type anywhere there is no need to use
map. It seems all you want to do is iterate over the returned result and possibly set a member on a book instance. In that case usetapinstead ofmap.mapis useful when you want to transform the input into a different output. - The code needs to make a distinction between an array and an object when performing an operation. That becomes easier to see when you define expected types in your method signatures for both inputs (method arguments) and the return type. The same goes for the naming of arguments, use plural form for arrays and singular form for non-array types. In this case use
booksandbook. - I would recommend using an interface over a class as you have no defined behavior. This is simpler when mapping parsed json to a type.
- Note that the constant boolean values are
trueandfalse, do not assign"True"/"False"as these are string literals and not boolean values. If you do a truthy comparison on"False"it will evaluate totrue
Books.ts
export interface IBook{
Name:string;
IsEnable:boolean;
IsEligible?:boolean|undefined;
}
books.component.ts
books: IBook[];
getBooksAsync() : Observable<IBook[]> {
return Observable.of([{"Name":"A", "IsEnable":false},{"Name":"B", "IsEnable":false}] as IBook[]);
}
isBookEligible(book: IBook): boolean {
return true; // hard coded for now because there is no implementation
}
ngOnInit(){
this.getBooksAsync.pipe(
tap((books) => {
books.forEach((book) => book.IsEligible = this.isBookEligible(book));
})
).subscribe(books => this.books = books);
}
回答2:
You can try this
this.books.pipe(
map( book => {
book.IsEnable = this.getEligibleBooks(book);
return book
})
).subscribe( data => console.log(data) );
回答3:
Rxjs of operator streams whole table at once. Rxjs map operator is mapping whole table to the new output. When you want to change items in the table you need to also use js map function to mutate whole table by checking all of the table items separately.
this.books.pipe(
map(
books => books.map( book => { ...book, IsEnable: this.getEligibleBooks(book) })),
).subscribe(data => console.log(data));
来源:https://stackoverflow.com/questions/55374349/how-to-use-map-and-assign-the-value-back