简体   繁体   中英

How to subscribe to class method that returns a rxjs observable?

I have a class method that uses BehaviorSubject and fromFetch from rxjs and returns an observable. I'm trying to subscribe to method outside of class.

I can console.log the method I get AnonymousSubject {_isScalar: false, observers: Array(0), closed: false, isStopped: false, hasError: false, …}

export class Client {
  constructor(opts) {
    ...
  }
  request(operation) {
    const option$ = new BehaviorSubject(null)
    const body = JSON.stringify({
      query: operation.query,
      variables: operation.variables
    })
    option$.next(body)

    return option$.pipe(
      switchMap(body => {
        return fromFetch(url, {
          method: 'POST',
          body,
          headers: {
            'Content-Type': 'application/json',
            ...fetchOpts.headers
          },
          ...fetchOpts
        }).pipe(
          switchMap(response => {
            if (response.ok) {
              // OK return data
              return response.json()
            } else {
              // Server is returning a status requiring the client to try something else.
              return of({
                error: true,
                message: `Error ${response.status}`
              })
            }
          }),
          catchError(err => {
            // Network or other error, handle appropriately
            console.error(err)
            return of({ error: true, message: err.message })
          })
        )
      })
    )
  }
}

I'm want to call method and subscribe to it like so

let client = new Client({...})

function handleRequest(operations) {
  let data = client.request(operations)
  data.subscribe(...)
}

When I add .subscribe to data it throws error: Uncaught TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. Uncaught TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Problem is that you are returning simple response.json() You should return an observable like of(response.json()) from switchMap's if (response.ok) block - See the code below -

export class Client {
  constructor(opts) {
    ...
  }
  request(operation) {
    const option$ = new BehaviorSubject(null)
    const body = JSON.stringify({
      query: operation.query,
      variables: operation.variables
    })
    option$.next(body)

    return option$.pipe(
      switchMap(body => {
        return fromFetch(url, {
          method: 'POST',
          body,
          headers: {
            'Content-Type': 'application/json',
            ...fetchOpts.headers
          },
          ...fetchOpts
        }).pipe(
          switchMap(response => {
            if (response.ok) {
              // OK return data
              return of(response.json())
            } else {
              // Server is returning a status requiring the client to try something else.
              return of({
                error: true,
                message: `Error ${response.status}`
              })
            }
          }),
          catchError(err => {
            // Network or other error, handle appropriately
            console.error(err)
            return of({ error: true, message: err.message })
          })
        )
      })
    )
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM