web-dev-qa-db-ja.com

Angular 2 RxJsサブスクライブからの戻りデータ

認証機能を備えたサービスがあります-

_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ソリューションはありますか?

15
Lordking

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 => {
                ...
            }
        )
    }
}
12
Lordking

リクエストに対応するオブザーバブルを直接返す必要があります。

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);
  }
);
4