title: Angular5.x progress reporting for long running server process
body: <p>We've run into a repeating design pattern in our django/angular5.x app that's
  caused us to write quite a bit of code that directly interacts with <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest" rel="nofollow noreferrer">XMLHttpRequest</a> and we wanted to see if anyone had come up with a better solution.</p>
  
  <p>Here's the pattern: Send a request to server which performs a long running operation (let's say 5 minutes). During the operation, the server emits a series of progress reports before responding with success/fail.</p>
  
  <p>For the purpose of this scenario, let's say the server was just emitting a series of progress reports such as the following django/python code:</p>
  
  <pre><code>def reports(request):
      return StreamingHttpResponse(stream())
  
  def stream():
      for num in range(10):
          yield '%d of 10\n' % num
          # simulate random 10 - 30 second delay
          time.sleep(random.randint(10, 30))
  </code></pre>
  
  <p>In Angular5.x we have service to report progress using the observer pattern:</p>
  
  <pre><code>@Injectable()
  export class ProgressService {
    constructor() { }
    progress() {
      let seen: number = 0;
      return Observable.create(observer =&gt; {
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 3 || xhr.readyState === 4) {
            observer.next(xhr.responseText.substring(seen);
            seen = xhr.responseText.length;
          }
        }
        xhr.open('POST', '/dosomething', true);
        xhr.send();
      });
    }
  }
  </code></pre>
  
  <p>This code works -- but it feels wrong to write something like this each time we interact with a long running service.</p>
  
  <p>We've looked at the angular2 <a href="https://angular.io/api/common/http/HttpClient" rel="nofollow noreferrer">HttpClient</a> and see it has a <code>reportProgress</code> option, but that would only seem to provide <a href="https://angular.io/api/common/http/HttpEventType#DownloadProgress" rel="nofollow noreferrer">HttpEventType.DownloadProgress</a>, which does not provide access to the <code>responseText</code> seen so far.  I've seen some references to Interceptors, but it's not clear how we'd need to manipulate these to extract the response body accumulated during progress reporting.</p>
  
  <p>Have we run into a limitation of the HttpClient infrastructure -- and we've developed the only viable solution? Or are we missing something blaringly obvious?</p>