0

I'm facing undefined data outside of subscribe, but it's getting inside of subscribe. I know, it's because of the Observable behavior. But how can I resolve this?

edit.ts

  ngOnInit(): void {
    let product
    this.productId = this.route.snapshot.paramMap.get('id')

    if (this.productId) {
      this.productService
        .getProductDetails(this.productId)
        .subscribe((response) => {
          product = response.data
          console.log(product)
        })
    }
    console.log(product)
    this.form = new FormGroup({
      productName: new FormControl(null, Validators.required),
      type: new FormControl(null, Validators.required),
      model: new FormControl(null)
    })
  }

service.ts

  getProductDetails(id: string) {
    return fromFetch(`http://localhost:3000/product/${id}`).pipe(
      switchMap((response) => {
        if (response.ok) {
          return response.json()
        } else {
          return of({ error: true })
        }
      })
    )
  }

Here, I want to access the product outside of subscribe.

Robin
  • 75
  • 1
  • 5
  • Does this answer your question? [How do I return the response from an Observable/http/async call in angular?](https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular) – R. Richards Aug 09 '22 at 12:01

2 Answers2

1

so the subscribe part will execute asynchronously, whereas the console.log outside the subscribe is synchronous. So there is no way to access the output of subscribe, outside of the subscribe. instead, move the code inside the subscribe.

ngOnInit(): void {
    let product
    this.productId = this.route.snapshot.paramMap.get('id')

    if (this.productId) {
      this.productService
        .getProductDetails(this.productId)
        .subscribe((response) => {
          product = response.data
          console.log(product)
          this.form.patchValue(product);
        })
    }
      

    this.form = new FormGroup({
        productName: new FormControl(null, Validators.required),
        type: new FormControl(null, Validators.required),
        model: new FormControl(null)
    })
  }

Reference to understand synchronous and asynchronous in javascript

Naren Murali
  • 19,250
  • 3
  • 27
  • 54
0

You don't necessarily need to access it outside of the subscribe handler, you can just build the form when the product becomes available:

ngOnInit(): void {
  this.route.paramMap
    .pipe(
      filter((map) => !!map.get('id')),
      // only if you still need this as a property
      tap((productId) => (this.productId = productId)),
      switchMap((productId) =>
        this.productService.getProductDetails(productId)
      ),
      map((response) => response.data)
    )
    .subscribe((product) => this.buildProductForm(product));
}

buildProductForm(product: any): void {
  this.form = new FormGroup({
    productName: new FormControl(null, Validators.required),
    type: new FormControl(null, Validators.required),
    model: new FormControl(null),
  });
}

Octavian Mărculescu
  • 4,312
  • 1
  • 16
  • 29