I've a service with an authenticate function -
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;
}
So if I call the authenticate function console.log(authenticate('a', 'b'));
, it logs undefined
since the ret
variable is returned before the subscribe function can put the data into it. How can I return the http response data from authenticate function? I've never done any reactive programming with RxJS before and that's what angular 2 seems to be using.
PS. Is there any decent CSP solution for javascript like go channels or core.async?
The subscribe() call returns a Subscription object that has an unsubscribe() method, which you call to stop receiving notifications.
Use operators to combine observables (not sure which one will be suitable in your case, possibly switchMap), then subscribe to resulting observable. Since you're dealing with things that cannot fully benefit from observables, it may be reasonable to switch to promises (async..
It's good to know that when you subscribe to an observer, each call of subscribe() will trigger it's own independent execution for that given observer. Subscribe calls are not shared among multiple subscribers to the same observable. The code inside an observables represents the execution of the observables.
I used Observables and Observers to build my solution. Since @Injectable creates a singleton class, I declared an Observable inside of it which I then exposed to my component. When I put any data into it, all subscribers get notified of the event. Warning: if you use this with zone.js 0.5, it won't work. Works with 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 => {
...
}
)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With