如何解决Typescript Angular,我如何调用 - 作为 Observables 链的一部分 - 对数组的每个成员进行操作并只返回成功计数?
我需要创建一个父记录,然后创建一系列子记录(顺序不重要)。然后我需要做一个后续的日志操作。
我知道如何通过将 observable 映射在一起来在 observable 上创建一系列单个动作,因此,我可以这样做:
-- 创建一个父记录,返回其id:
createParentRecord(parentInfo: parentType): Observable<number>
-- 创建一个子记录,返回其id
createChildRecord(childInfo: childType): Observable<number>
-- 记录条目
logStuff(parentId: number,childId: number)
-- 复合函数完成所有工作,返回 parentId
doTheThing(): Observable<number> {
/* ... */
let parentId: number;
let childId: number;
return createParent(parentInfo).pipe(
tap(id => (parentId = id)),mergeMap(id => { childInfo.parentId = parentId; return createChildRecord(childInfo);} ),mergeMap(childId => { childInfo.childId = childId; return logStuff(parentId,childId); ),map( () => parentId)
);
}
问题
这很好用。
但是如果我有 childInfo[] 而不是 childInfo,我该怎么做? 如何处理要订阅并返回内部可观察结果的 childInfo[] 数组? 我只想要一个成功的数字 - 或者只是每个可观察对象返回的任何结果? 我使用 forkJoin() 吗?
我这辈子都搞不清楚。帮助?
解决方法
如果我理解正确你的问题,我会这样进行。评论是内联的
function doTheThing(): Observable<any> {
/* ... */
let parentId: number;
// somehow there is an array of children info to be saved
const childInfos = new Array(3).fill({})
return createParent('Parent Info').pipe(
tap(id => (parentId = id)),concatMap(id => {
// each childInfo is filled with the result of the createParent operation
childInfos.forEach(c => c.parentId = parentId);
// an array of Observable is created - each one represents a createChildRecord operation
const childInfosObs = childInfos.map(ci => createChildRecord(ci))
// all child record operations are executed in parallel via forkJoin
return forkJoin(childInfosObs);
}),concatMap(childIds => {
// forkJoin returns an array of results with the same order as the array of Observables passed to forkJoin
// therefore we can loop through the array and set each childInfo with its result
childInfos.forEach((ci,i) => ci.childId = childIds[i])
// last thing we do is to log and then return the results of the forkJoin
return logStuff(parentId,childIds).pipe(
map(() => childIds)
);
} )
);
}
请注意,我使用 concatMap
而不是 mergeMap
。除非有特定原因,否则无论何时我进行 DB 或 Rest 操作,我更喜欢 concatMap
只是为了保持操作顺序。
如果需要,您还可以使用一些错误处理逻辑来丰富 childInfosObs
中包含的每个 observable,考虑到 forkJoin
会在它尝试执行任何 Observable 时出错。
Here a stackblitz 以建议的解决方案为例。
,块引用
您可以将 ChildInfo[]
映射到一个 observable 数组,然后像这样合并它:
return createParent(parentInfo).pipe(
tap(newParentId => parentId = newParentId),mergeMap(newParentId => forkJoin(
childInfos.map(childInfo => { // this is an Array map.
childInfo.parentId = parentId;
return createChildRecord(childInfo); // this should return childInfo,since it sounds like a CRUD operation.
})
)),
请注意,这仅在 createChildRecord
完成时才有效,因为 forkJoin
不会在其他情况下发出。我认为这是我的解决方案中的一个调用。
如果您让 createChildRecord
返回您的 childInfo 的更新版本,那么在以下操作中您的生活也会变得更加轻松。
createChildRecord(childInfo: ChildInfo): Observable<ChildInfo> {
const childId = /** TBD **/
return of({...childInfo,childId});
}
为了可读性,考虑将内部 observable 放在某种方法中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。