0

I have a problem in my application:

Often happens that the code is not sinchronized with the api call:

service method

Initialize(_idUser: number,_BusinessName: string, _VAT: string, _FiscalCode: string): Customer {

    var req: ReqCustomerInitialize = {
      idUser: _idUser,
      BusinessName: _BusinessName,
      VAT: _VAT,
      FiscalCode: _FiscalCode
    };

    var x = this.http.post(this.baseUrl + "initialize", req, this.getRequestOptions)
      .map(response => response.json())
      .catch(this.handleError)
      .subscribe(data => {

        this._customer = data;

      }
      );
    return this._customer;
  }

component with method call

import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from "@angular/forms";
import { AuthService } from "../services/auth.service";
import { CustomerService } from "../services/customer.service";
import { Router } from "@angular/router";
import { Customer } from '../model/customer';


@Component({
  selector: 'app-customer-initialize',
  templateUrl: './customer-initialize.component.html',
  styleUrls: ['./customer-initialize.component.css']
})
export class CustomerInitializeComponent implements OnInit {

  title = "Initialize";
  FormCustomerCreate = null;
  ErrorOffertCreate = false;
  customer: Customer;

  constructor(
    private customerService: CustomerService,
    private fb: FormBuilder,
    private router: Router,
    private authService: AuthService) {
    if (!this.authService.isLoggedIn()) {
      this.router.navigate([""]);
    }
    this.FormCustomerCreate = fb.group({
      BusinessName: ["", Validators.required],
      VAT: ["", Validators.maxLength(30)],
      FiscalCode: ["", Validators.maxLength(30)]
    });
  }

  ngOnInit() {
  }

  do_CustomerInitialize(e) {
    e.preventDefault();
    
    var _BusinessName = this.FormCustomerCreate.value.BusinessName;
    var _VAT = this.FormCustomerCreate.value.VAT;
    var _FiscalCode = this.FormCustomerCreate.value.FiscalCode;

    this.customer = this.customerService.Initialize(0,_BusinessName,_VAT,_FiscalCode);
    alert(this.customer.idCustomer);    //GENERATE ERROR
    this.router.navigate(['CustomerDetail', this.customer.idCustomer]);
  }
}

The situation is this:

On fist call of do_CustomerInitialize, the Api is properly called but I get Javascript runtime error in this line of code:

alert(this.customer.idCustomer);    //GENERATE ERROR

TypeError: this.customer is undefined

The second time that I call the function, all works, the api is called again and the alert provides me the idCustomer value...

I think that it is a Sync/Async call problem.

How can I avoid this problem? I have to route the application only when I have the idCustomer valorized...

Thanks to support Ciao

Community
  • 1
  • 1
DarioN1
  • 2,460
  • 7
  • 32
  • 67
  • 3
    Duplicate of [How do I return the response from an Observable/http/async call in angular2?](http://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular2) – n00dl3 Apr 14 '17 at 10:15
  • Thanks n00dl3, your link helps but actually I need support on how I can switch Initialize method in a sync method and in a faster way – DarioN1 Apr 14 '17 at 10:20
  • 2
    Sorry, but you can't switch from async to sync, synchronous ajax being a very bad practice and deprecated in browsers... That's a duplicate. – n00dl3 Apr 14 '17 at 10:22

2 Answers2

1

You can try the following:

1) move subscribe block from service to component so your service returns Observable:

Initialize(_idUser: number,_BusinessName: string, _VAT: string, _FiscalCode: string): Observable<Customer> {

  var req: ReqCustomerInitialize = {
    idUser: _idUser,
    BusinessName: _BusinessName,
    VAT: _VAT,
    FiscalCode: _FiscalCode
  };

  return this.http.post(this.baseUrl + "initialize", req, this.getRequestOptions)
    .map(response => response.json())
    .catch(this.handleError);
}

2) do logic inside subscribe inside your component:

do_CustomerInitialize(e) {
  e.preventDefault();

  var _BusinessName = this.FormCustomerCreate.value.BusinessName;
  var _VAT = this.FormCustomerCreate.value.VAT;
  var _FiscalCode = this.FormCustomerCreate.value.FiscalCode;

  this.customerService.Initialize(0,_BusinessName,_VAT,_FiscalCode)
    .subscribe(data => {
      this.customer = data;
      alert(this.customer.idCustomer);
      this.router.navigate(['CustomerDetail', this.customer.idCustomer]);
    }
}
Mikhail Romanov
  • 1,542
  • 1
  • 13
  • 20
1

Initialize function should return observable.

Initialize(_idUser: number,_BusinessName: string, _VAT: string, _FiscalCode: string): Customer {

    var req: ReqCustomerInitialize = {
      idUser: _idUser,
      BusinessName: _BusinessName,
      VAT: _VAT,
      FiscalCode: _FiscalCode
    };

    return this.http.post(this.baseUrl + "initialize", req, this.getRequestOptions)
      .map(response => response.json())
  }

Then in your component

    do_CustomerInitialize(e) {
            e.preventDefault();

            var _BusinessName = this.FormCustomerCreate.value.BusinessName;
            var _VAT = this.FormCustomerCreate.value.VAT;
            var _FiscalCode = this.FormCustomerCreate.value.FiscalCode;

            this.customer = this.customerService.Initialize(0,_BusinessName,_VAT,_FiscalCode).subscribe(( => {
                alert(this.customer.idCustomer);    //GENERATE ERROR
                this.router.navigate(['CustomerDetail',this.customer.idCustomer]);
            }));
     }

But I think you are looking for BehaviorSubject. Here is example

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { User } from './user';

@Injectable()
export class UserService {
    user: BehaviorSubject<User>;

    constructor(private http:Http) {
        this.user = new BehaviorSubject(new User({}));
    }

    public init() {
        this.http.get(window['Routing'].generate('api_v1_user_get_profile'))
            .map(response => response.json())
            .subscribe(user => {
                    this.user.next(new User(user['data']));
                }
            );
    }

    getUser() {
        if (!(this.user instanceof User)) {
            this.init();
        }
        return this.user.asObservable();
    }
}

And here is more info http://www.developersite.org/101-218532-angular2

Victor Bredihin
  • 2,220
  • 21
  • 30
  • Hi Victor, I tried your first example but I get 'Property 'subscribe' does not exist on type 'Customer'. Should I also modify the class Customer? – DarioN1 Apr 14 '17 at 13:14