我试图理解可观察物并遇到一些挫折。
我有一个save()
函数,可以调用initialize()
来获取一些ID。在初始化内部,我在map方法(payload
)中设置一个Observable,当我将结果记录到控制台时,它会被设置为正确的值。我试过切换地图订阅无济于事。
TLDR;从地图/订阅内部为预先提升的变量设置值的正确方法是什么?
相关:如果从对象序列化,那么observable的正确类型是什么?
save(post: Post, draftId?: number, postId?: number): Observable<any> {
let payload: Observable<any>;
if (!postId) {
post.state = post.state ? post.state : 'unsaved';
this.initialize(post)
.subscribe((res) => { //error here... cannot run
console.log('Waypoint: posts.service.ts:36');
payload = res;
});
} else if (draftId && postId) {
post.state = 'autosaved'
return this.updateDraft(post, draftId);
};
return payload;
}
initialize(post: Post): Observable<any> {
let resultPost: number;
let resultDraft: number;
var payload: Observable<any>;
this.createPost(post)
.subscribe(res => {
resultPost = res.id;
post.postId = res.id
this.createDraft(post)
.map(res => {
resultDraft = res.id;
let _payload = {
postId: resultPost,
draftId: resultDraft
};
console.log('Waypoint: posts.service.ts:62');
payload = Observable.create(_payload); // looks good!
}, (error) => { console.log(error) }).subscribe();
});
console.log(payload); //undefined :(
return payload;
}
答案 0 :(得分:1)
如果我理解正确,你的逻辑或多或少会像这样
createPost
方法创建一个帖子,该方法返回一个
Observable
subcribe
到createPost
并获得包含的结果
帖子ID createDraft
再次返回Observable
subscribe
到createDraft
,结果草稿
ID 强> 我认为这是对的,你应该瞄准的是这样的事情
let postId;
let draftId;
this.createPost(post)
.map(res => {postId = res.id})
.mergeMap(() => this.createDraft(post)) // mergeMap is same as flatMap
.map(res => {draftId = res.id})
.map(() => [postId, draftId])
.subscribe(postDraftIds => payload = postDraftIds)
还有其他方法可以使用Observable运算符来达到相同的目标(例如,您可以使用switchMap而不是mergeMap - 这是一个解释how switchMap works的非常好的链接),但我希望这很清楚
答案 1 :(得分:1)
回答你的一些问题:
的console.log(有效载荷);是未定义的,因为这行代码是在this.createDraft的订阅发生之前执行的
您使用的订阅方式太多,应该只有一个,实际上您想要接收数据的位置,在以前的情况下,您可以使用例如map/flatMap
运算符。使用适当的运算符可以显着降低代码复杂性,如:
save(post: Post, draftId?: number, postId?: number): Observable<Payload> {
if (!postId) {
post.state = post.state ? post.state : 'unsaved';
return this.initialize(post);
} else if (draftId && postId) {
post.state = 'autosaved'
return this.updateDraft(post, draftId);
}
return Observable.empty();
}
initialize(post: Post): Observable<Payload> {
let resultPost: number;
return this.createPost(post)
.flatMap(res => {
resultPost = res.id;
post.postId = res.id;
return this.createDraft(post)
}.map(res => new Payload(resultPost, res.id));
}}
导出类Payload { postId:number; draftId:number;
constructor(postId: number, draftId: number) {
this.postId = postId;
this.draftId = draftId;
}
}
事实上,initialize
可以更多地重构为:
initialize(post: Post): Observable<Payload> {
return this.createPost(post)
.flatMap(res => {
return Observable.zip(res.id, this.createDraft(post))
}).map(res => new Payload(res[0], res[1].id));
}
any
,而是使用特定类型注意:我没有运行此代码,我只是建议您使用运算符
//不知道为什么Payload没有正确呈现......