在 RxJS 中修补获取的对象的最佳方法是什么?
What is the best way to patch fetched objects in RxJS?
我有一个代码可以通过 id 获取图书
const fetchBook = (bookId: number) => {
const title = 'Book' + bookId;
// mimic http request
return timer(200).pipe(mapTo({ bookId, title }));
}
const bookId$ = new Subject<number>();
const book$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId)),
shareReplay(1)
);
book$.subscribe(book => console.log('book title: ', book.title))
bookId$.next(1);
我有一个 API 方法来修补值和 returns 更新的对象:
const patchBook = (bookId: number, newTitle: string) => {
return timer(200).pipe(mapTo({ bookId, title: newTitle }));
}
在我调用 patchBook(1, 'New Book Title')
后,我应该怎么做才能让 book$
发出新值?
我可以将 book$
显式声明为 Subject
并手动更新它。但这将是势在必行的,而不是被动的方法。
更新: 补丁被调用作为用户操作的结果在任何时候(或从不)
Upd2: 实际上 book$
也可以在服务器端更改,我的真实代码如下所示:
const book$ = combineLatest([bookId$, currentBookChangedServerSignal$]).pipe...
与将 bookId 转换为 Book 所做的操作相同,您可以使用将 Book 转换为 patchBook。
const book$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId)),
mergeMap(({bookId, title}) => patchBook(bookId, title)),
shareReplay(1)
);
更新:
patch
并不总是被称为
有很多方法可以做到这一点,“最佳”方法实际上取决于您构建系统的方式。
假设您动态创建了一个用户单击的按钮,这会触发更新事件。
const patchBtn = document.createElement("button");
const patchBook$ = fromEvent(patchBtn, 'click').pipe(
switchMap(_ => patchBook(bookId, title))
);
const basicBook$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId))
);
const book$ = merge(patchBook$, basicBook$).pipe(
shareReplay(1)
);
您可能希望 fromEvent
事件发出一些数据,而不是通过单击将 (bookId, title)
硬编码到流中,但您明白了。这只是完成工作的众多方法之一。
当然,删除 bookId$
几乎总是可能的(并且是可取的),并用更具反应性的机制替换它,该机制以声明方式挂钩到 whatever/wherever ID 的来源首先。
您可以声明一个 fetchBook$
可观察对象和一个 patchBook$
主题。然后你的 book$
observable 可以是两者的合并。
const patchBook = (bookId: number, newTitle: string) => {
return timer(200).pipe(
mapTo({ bookId, title: newTitle }),
tap(newBook=>this.patchBook$.next(newBook))
);
}
const bookId$ = new Subject<number>();
const fetchBook$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId)),
shareReplay(1)
);
const patchBook$ = Subject<{ bookId: number, newTitle: string}>();
const book$ = merge(fetchBook$, patchBook$);
book$.subscribe(book => console.log('book title: ', book.title))
bookId$.next(1);
patchBook(2, 'Moby Dick');
我有一个代码可以通过 id 获取图书
const fetchBook = (bookId: number) => {
const title = 'Book' + bookId;
// mimic http request
return timer(200).pipe(mapTo({ bookId, title }));
}
const bookId$ = new Subject<number>();
const book$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId)),
shareReplay(1)
);
book$.subscribe(book => console.log('book title: ', book.title))
bookId$.next(1);
我有一个 API 方法来修补值和 returns 更新的对象:
const patchBook = (bookId: number, newTitle: string) => {
return timer(200).pipe(mapTo({ bookId, title: newTitle }));
}
在我调用 patchBook(1, 'New Book Title')
后,我应该怎么做才能让 book$
发出新值?
我可以将 book$
显式声明为 Subject
并手动更新它。但这将是势在必行的,而不是被动的方法。
更新: 补丁被调用作为用户操作的结果在任何时候(或从不)
Upd2: 实际上 book$
也可以在服务器端更改,我的真实代码如下所示:
const book$ = combineLatest([bookId$, currentBookChangedServerSignal$]).pipe...
与将 bookId 转换为 Book 所做的操作相同,您可以使用将 Book 转换为 patchBook。
const book$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId)),
mergeMap(({bookId, title}) => patchBook(bookId, title)),
shareReplay(1)
);
更新:
patch
并不总是被称为
有很多方法可以做到这一点,“最佳”方法实际上取决于您构建系统的方式。
假设您动态创建了一个用户单击的按钮,这会触发更新事件。
const patchBtn = document.createElement("button");
const patchBook$ = fromEvent(patchBtn, 'click').pipe(
switchMap(_ => patchBook(bookId, title))
);
const basicBook$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId))
);
const book$ = merge(patchBook$, basicBook$).pipe(
shareReplay(1)
);
您可能希望 fromEvent
事件发出一些数据,而不是通过单击将 (bookId, title)
硬编码到流中,但您明白了。这只是完成工作的众多方法之一。
当然,删除 bookId$
几乎总是可能的(并且是可取的),并用更具反应性的机制替换它,该机制以声明方式挂钩到 whatever/wherever ID 的来源首先。
您可以声明一个 fetchBook$
可观察对象和一个 patchBook$
主题。然后你的 book$
observable 可以是两者的合并。
const patchBook = (bookId: number, newTitle: string) => {
return timer(200).pipe(
mapTo({ bookId, title: newTitle }),
tap(newBook=>this.patchBook$.next(newBook))
);
}
const bookId$ = new Subject<number>();
const fetchBook$ = bookId$.pipe(
switchMap(bookId => fetchBook(bookId)),
shareReplay(1)
);
const patchBook$ = Subject<{ bookId: number, newTitle: string}>();
const book$ = merge(fetchBook$, patchBook$);
book$.subscribe(book => console.log('book title: ', book.title))
bookId$.next(1);
patchBook(2, 'Moby Dick');