javascript - Angular observable post and subscribe explanationHow it works - Stack Overflow

admin2025-04-08  1

Explanation of Observable Post

setupponent.ts

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

import { Post } from './model/post';
import { PostService } from './service/post.service';

@Component({
  selector: 'setup',
  templateUrl: './setupponent.html',
  styleUrls: ['./setupponent.scss']
})
export class SetupComponent implements OnInit {

  @Output()
  change: EventEmitter<string> = new EventEmitter();

  postUsers(input){
    this.postService.postUser(input)
      .subscribe(
        post => {
          this.post = post
        },
        err => {
          console.log(err);
        });
  }

  clicked(value) {
    console.log(value);
    this.postUsers(this.input)
    // this.change.emit(value);
  }

  plexForm : FormGroup;
  constructor(private postService: PostService) {}

  post: Post[];

  ngOnInit() {}

}

post.service.ts

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Post } from '../model/post';
import { Observable } from 'rxjs/Rx';

// Import RxJs required methods
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class PostService {

  constructor (private http: Http) {}
  private registerUrl = 'http://localhost:2001/api/users/register';

  postUser(user:Post) : Observable<Post[]>{
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    return this.http.post(this.registerUrl, user, options)
      .map(this.extractData)
      .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body || { };
  }
  private handleError (error: Response | any) {
    // In a real world app, you might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

}

model/post.ts

export class Post {
    constructor(
        public id: number, 
        public name: string, 
        public email: string, 
        public password: string
    ){}
}

I understand what the model/post.ts does, it defines the property types, what I need is clarification on the subscribe method within setupponents.ts. The Observable gets invoked inside clicked() but what I want to understand is how does this because accessible to the application so that I can proceed after the action has run its course this.postUsers(this.input)

Typically with a Promise I would have done the following

this.postUsers(this.input)
  .then(function(){
  });

I'd really like it if someone could explain how it works and how to achieve a confirmation that the post has pleted to then run the next function

ie I have this

clicked(value) {
    console.log(value);
    this.postUsers(this.input)
    // this.change.emit(value);
  }

but in promise I'd do

  clicked(value) {
    console.log(value);
    this.postUsers(this.input)
      .then(function(){
        this.change.emit(value);
      });
  }

How can I get this to work with Observables? I tried to see what was returned by doing

  clicked(value) {
    console.log(value);
    const runThis = this.postUsers(this.input);
    console.log(runThis);
    // this.change.emit(value);
  }

but it returns undefined.

Explanation of Observable Post

setup.ponent.ts

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

import { Post } from './model/post';
import { PostService } from './service/post.service';

@Component({
  selector: 'setup',
  templateUrl: './setup.ponent.html',
  styleUrls: ['./setup.ponent.scss']
})
export class SetupComponent implements OnInit {

  @Output()
  change: EventEmitter<string> = new EventEmitter();

  postUsers(input){
    this.postService.postUser(input)
      .subscribe(
        post => {
          this.post = post
        },
        err => {
          console.log(err);
        });
  }

  clicked(value) {
    console.log(value);
    this.postUsers(this.input)
    // this.change.emit(value);
  }

  plexForm : FormGroup;
  constructor(private postService: PostService) {}

  post: Post[];

  ngOnInit() {}

}

post.service.ts

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Post } from '../model/post';
import { Observable } from 'rxjs/Rx';

// Import RxJs required methods
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class PostService {

  constructor (private http: Http) {}
  private registerUrl = 'http://localhost:2001/api/users/register';

  postUser(user:Post) : Observable<Post[]>{
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    return this.http.post(this.registerUrl, user, options)
      .map(this.extractData)
      .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body || { };
  }
  private handleError (error: Response | any) {
    // In a real world app, you might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

}

model/post.ts

export class Post {
    constructor(
        public id: number, 
        public name: string, 
        public email: string, 
        public password: string
    ){}
}

I understand what the model/post.ts does, it defines the property types, what I need is clarification on the subscribe method within setup.ponents.ts. The Observable gets invoked inside clicked() but what I want to understand is how does this because accessible to the application so that I can proceed after the action has run its course this.postUsers(this.input)

Typically with a Promise I would have done the following

this.postUsers(this.input)
  .then(function(){
  });

I'd really like it if someone could explain how it works and how to achieve a confirmation that the post has pleted to then run the next function

ie I have this

clicked(value) {
    console.log(value);
    this.postUsers(this.input)
    // this.change.emit(value);
  }

but in promise I'd do

  clicked(value) {
    console.log(value);
    this.postUsers(this.input)
      .then(function(){
        this.change.emit(value);
      });
  }

How can I get this to work with Observables? I tried to see what was returned by doing

  clicked(value) {
    console.log(value);
    const runThis = this.postUsers(this.input);
    console.log(runThis);
    // this.change.emit(value);
  }

but it returns undefined.

Share Improve this question asked Jul 13, 2017 at 10:17 user6885115user6885115 1
  • is there still anything unclear in my answer? – Max Koretskyi Commented Jul 17, 2017 at 17:59
Add a ment  | 

2 Answers 2

Reset to default 4

Similar with promises make your postUsers method return an observable (not a subscription)

postUsers(input){
    return this.postService.postUser(input);
}

Then you can subscribe to this method like using a then in promises.

clicked(value) {
    console.log(value);
    this.postUsers(this.input).subscribe((response)=> {
        this.change.emit(value);
    });
}

You can also convert observables into promises. Then you wouldn't get confused.

import 'rxjs/add/operator/toPromise';

postUsers(input){
    return this.postService.postUser(input).toPromise();
}

clicked(value) {
    console.log(value);
    this.postUsers(this.input)
      .then((res)=>{
        this.change.emit(value);
      });
}

Note that I haven't used the function keyword in my callbacks. If I did this.change would refer to the callbacks change because the this wouldn't refer to the ponent.

how to achieve a confirmation that the post has pleted

When the stream triggers plete callback you will know the request has pleted. This is the third callback you pass to the subscribe method or the plete method if you pass observer object instead of callbacks.

I think you will benefit from knowing how the operator toPromise work. You can then use it directly or emulate its logic. You can use it:

this.postUsers(this.input).toPromise()
  .then(function(){
     ...
  });

Basically what it does is creates a promise and returns it. Then it subscribes the the observable returned by the this.postUsers and waits until this observable emits pleted event. After that, it resolves the promise with the last event it returned. Something along these lines:

toPromise(observable) {
   let lastReturnedValue = null;
   return new Promise() {
      observable.subscribe(
      (v)=>{
            lastReturnedValue = v;
      },
      (e)=>{
            reject(e);
      },      
      (c)=>{
            resolve(lastReturnedValue);
      });
   }
}

So just as with toPromise you can subscribe to the observable and listen for plete event:

  clicked(value) {
    console.log(value);
    this.postUsers(this.input).subscribe(
    (v)=>{ // here you get the value and can save it },
    (e)=>{ // here you know that observable has error, similar to `catch` callback },
    ()=>{ // here you know that observable has pleted, similar to `then` callback}
    );
    console.log(runThis);
    // this.change.emit(value);
  }

Or you can return the observable for someone else to listen:

  clicked(value) {
    return this.postUsers(this.input)
  }

  ...
  clicked().subscribe( // all the code from previous example)
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1744124727a232411.html

最新回复(0)