J'ai un service avec une fonction d'authentification -
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;
}
Donc, si j'appelle la fonction d'authentification console.log(authenticate('a', 'b'));
, elle enregistre undefined
puisque la variable ret
est retournée avant que la fonction d'abonnement puisse y mettre les données. Comment puis-je renvoyer les données de réponse http à partir de la fonction d'authentification? Je n'ai jamais fait de programmation réactive avec RxJS auparavant et c'est ce que angular 2 semble utiliser.
PS. Existe-t-il une solution CSP décente pour javascript comme go channels ou core.async?
J'ai utilisé Observables et Observers pour créer ma solution. Puisque @Injectable crée une classe singleton, j'ai déclaré un observable à l'intérieur de celle-ci que j'ai ensuite exposé à mon composant. Lorsque j'y mets des données, tous les abonnés sont informés de l'événement. Attention: si vous l'utilisez avec zone.js 0.5, cela ne fonctionnera pas. Fonctionne avec 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 => {
...
}
)
}
}
Vous devez renvoyer directement l'observable correspondant à votre demande:
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());
}
Et l'appelant de la méthode authenticate
doit s'y abonner pour recevoir le résultat:
this.service.authenticate('username', 'password').subscribe(
(result) => {
console.log('Result received');
console.log(result);
}
);