3

I am in the early phases of an Angular 4 project trying to create a client for my http services. These services can return one of two things:

  1. The actual desired json response from the service with an http status of 200, or
  2. A guid which represents a job token with which I can poll for status of the long-running job, and an http status of 202.

When the service returns a 200 status, I want to just return its json content directly, so that's easy enough.

When the result status is a 202, I then want to poll a separate url with that token and receive a json object with status info. When that status info indicates completion, I want to then make a request to a final url that will return the output.

I'm not sure how to handle the conditional logic that I need within the request. I suspect I could use repeatWhen to monitor the result of the polling request, but I'm having trouble figuring out how to use it.

http.request('/some/longrunning/job')
    .flatMap((resp: Response) => {
        if (resp.status !== 202)
            return Observable.of(resp);

        var job_token = resp.json().token;
        return http.get('/jobstatus/' + job_token)
            // result from this endpoint is a json object that looks something
            // like { status: 'running' } or { status: 'complete' }
            .repeatWhen(function (polling_resp: Observable<Response>) {
                // How do I use polling_resp here to look at my http response?
                // Do I need to explicitly subscribe to it? And if so,
                // how then do I inspect the response and return the
                // appropriate value to indicate whether or not to
                // resubscribe via the repeatWhen?
            });
    });

Can someone give me some hints on how to use logic in the repeatWhen? I haven't seen any examples that use content from the observable itself to decide whether to resubscribe.

1 Answer 1

9

I think you are looking for something more like this:

http.request('/some/longrunning/job')
    .flatMap((resp: Response) => {
      if (resp.status !== 202)
          return Observable.of(resp);
      const token = resp.json().token;

      return http.get(`/jobstatus/${token}`)

        // You can use repeatWhen if you need more nuanced logic for
        // how many times you want this to repeat, and how it should 
        // space out repeat attempts.
        // This is just an example that guarantees at least 1 second between
        // poll attempts so as to not overload the server
        .repeatWhen(c => c.debounceTime(1000))

        // Ignore values until you have completed
        .skipWhile(resp => resp.json().status !== 'completed')

        // At this point you can stop the polling
        .take(1)

        // You don't actually care about the value of the response
        // just that it has "completed" this maps that response to the
        // call to fetch the result status.
        .flatMapTo(http.get(`/jobresult/${token}`))

    });

Essentially your first conditional is correct, the second part you need to kick off the request and continually repeat it, the skipWhile portion will inspect the results and will not propagate them until the status is marked as complete, you can then use flatMapTo to convert that resulting message directly into another API request to get the actual result which then gets propagated.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.