【问题标题】:Angular 2 return data from RxJs subscribeAngular 2 从 RxJs 订阅返回数据
【发布时间】: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 使用的任何事件流机制。

标签: angular typescript asynchronous 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 => {
                ...
            }
        )
    }
}

【讨论】:

  • 什么是“私人观察者:观察者”中的通知?我可以传递给观察者什么?
  • 只需将 替换为
猜你喜欢
  • 2017-02-23
  • 2016-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多