RxJS v5.x:如何让首个Observable完成后映射结果传给第二个?
如何在RxJS中让第二个Observable等待第一个完成并传递结果?
我正在学习RxJS,习惯了同步编程的我对此感到吃力。我需要组合两个Observable:
- 第一个是
login(Observable<any>),完成后需映射出结果中的token属性:
获取token的方式:const login = this.userService.login({ username: username, password: password });login.pipe(map(res => res.token)); - 第二个是
storage(Observable<boolean>),需接收上述token并返回对应Observable:const store = this.localStorage.setItem('token', token);
请问如何将login映射后的结果传给storage,并让storage等待login完成?
我尝试了如下代码,但不确定第二个Observable是否会等待第一个完成:
return this.userService.login({username: username, password: password}) .pipe( map(res => res.token), mergeMap(token => this.localStorage.setItem(AUTH_TOKEN_KEY, token)), tap(res => console.log(res)) // boolean true );
你的代码完全正确!
嘿,别担心,你写的这段代码完美契合你的需求~ 我来给你拆解一下它的工作逻辑:
loginObservable的执行:this.userService.login(...)发起的登录请求是一个单次发射的Observable——请求成功后发射结果,随即完成,不会重复发射值。map提取token:map(res => res.token)是同步的转换操作,它把登录返回的完整结果转换成我们需要的token值,不会打乱Observable的执行顺序。mergeMap实现顺序执行:这里的mergeMap就是实现“等第一个Observable完成再执行第二个”的核心。因为login只会发射一次就完成,mergeMap会等待它输出token后,才会调用this.localStorage.setItem(token)创建第二个Observable并订阅它。
额外补充一点:如果你的login Observable存在多次发射的可能(当然登录场景基本不会),mergeMap会同时订阅后续产生的存储Observable,但在你的场景里完全不用考虑这个情况。如果想更直观地表达“严格按顺序执行,前一个完成再启动下一个”,也可以替换成concatMap,它和mergeMap在处理单次发射的Observable时效果完全一致。
最后,tap(res => console.log(res))也能帮你验证流程:只有登录成功拿到token、并且存储操作完成后,才会打印这个true,这刚好证明了两个Observable是按顺序执行的。
内容的提问来源于stack exchange,提问作者gremo
相关产品推荐
相关产品推荐

