Angular 2 从 RxJs 订阅返回数据
Posted
技术标签:
【中文标题】Angular 2 从 RxJs 订阅返回数据【英文标题】:Angular 2 return data from RxJs subscribe 【发布时间】:2016-07-20 11:03:26 【问题描述】:我有一个具有身份验证功能的服务 -
authenticate(username: string, password: string)
let ret;
let packet = JSON.stringify(
username: username,
password: password
);
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post('http://localhost:5000/api/authenticate/', packet,
headers: headers
)
.map(res => res.json())
.subscribe(
data =>
// put return data into ret
ret = data.token;
,
err => console.log(err),
() =>
// this works!
console.log(ret);
);
// get's returned before I put data into it
return ret;
所以如果我调用验证函数console.log(authenticate('a', 'b'));
,它会记录undefined
,因为ret
变量在订阅函数可以将数据放入其中之前返回。如何从身份验证函数返回 http 响应数据?我以前从来没有用 RxJS 做过任何反应式编程,这就是 angular 2 似乎正在使用的东西。
PS。有没有像 go channels 或 core.async 这样像样的 javascript 的 CSP 解决方案?
【问题讨论】:
这并不是 async 或 RxJs 的真正工作方式;您不会从异步函数返回数据。 我想了这么多,因为在我返回 ret 变量后 subscribe 被执行。关于在处理 RxJS 时如何返回数据的任何想法? 你可以创建另一个方法,比如 this.authenticateFinished(ret) console.log(ret); // 和其他任何东西 然后从 data => 调用它 好吧,subscribe
在您返回之前执行,但它是异步的。我不知道 AngJS 的“方式”是什么,但你要么需要回调,要么需要观察者,或者 RxJS 使用的任何事件流机制。
【参考方案1】:
您需要直接返回与您的请求对应的可观察对象:
authenticate(username: string, password: string)
let ret;
let packet = JSON.stringify(
username: username,
password: password
);
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:5000/api/authenticate/', packet,
headers: headers
)
.map(res => res.json());
authenticate
方法的调用者必须订阅它才能接收结果:
this.service.authenticate('username', 'password').subscribe(
(result) =>
console.log('Result received');
console.log(result);
);
【讨论】:
谢谢。但是,我希望所有逻辑都进入服务而不是组件内部。我想通了。【参考方案2】:我使用 Observables 和 Observers 来构建我的解决方案。由于@Injectable 创建了一个单例类,我在其中声明了一个 Observable,然后将其暴露给我的组件。当我将任何数据放入其中时,所有订阅者都会收到该事件的通知。警告:如果你将它与 zone.js 0.5 一起使用,它将无法工作。适用于 0.6。
import Observable from 'rxjs/Observable';
import Observer from 'rxjs/Observer';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';
@Injectable()
export class AuthService
// expose to component
notification$: Observable<Notification>;
private observer: Observer<Notification>;
....
constructor(private http: Http)
this.notification$ = new Observable(observer => this.observer = observer).share();
authenticate(username, password)
let packet = JSON.stringify(
username: username,
password: password
);
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post(`$this.baseUri/authenticate/`, packet,
headers: headers
)
.map(res => res.json())
.subscribe(
data =>
if (data.success && data.token)
this.saveJwt(data.token);
else
this.deleteJwt();
// put data into observavle
this.observer.next(
message: data.message,
type: data.success
);
,
err =>
// put data into observavle
this.observer.next(
message: 'Error connecting to server',
type: false
)
,
() =>
);
export class AuthComponent implements OnInit
observable: Observable<Notification>;
...
ngOnInit()
// subscribe to the observable
this.observable = this.authService.notification$;
this.observable.subscribe(
data =>
...
)
【讨论】:
什么是“私人观察者:观察者以上是关于Angular 2 从 RxJs 订阅返回数据的主要内容,如果未能解决你的问题,请参考以下文章
Angular中利用rxjs库的Subject多播解决在第一次订阅时进行初始化操作(如第一次订阅时从服务器获取数据)
Angular 7 RxJs - HTTP 调用未在 ForkJoin 中完成
Angular / RxJs对一个observable的多个订阅