apollo-angular icon indicating copy to clipboard operation
apollo-angular copied to clipboard

Add support for request progress

Open szechyjs opened this issue 6 years ago • 14 comments

Angular now provides support for monitoring the progress of HTTP requests through an observable.

https://angular.io/guide/http#listening-to-progress-events

It would be great if this could be exposed through apollo-angular.

szechyjs avatar Mar 27 '18 13:03 szechyjs

If you're interested in posting a PR, I could guide you and give some help. Just let me know.

kamilkisiela avatar Apr 01 '19 18:04 kamilkisiela

@kamilkisiela I would like to work on it.

Here is my thought how to implement it:

  1. Extend HttpRequestOptions type add new field reportProgress?: boolean
  2. Add that new field to request creation
const req: Request = {
          .....
          options: {
            ....
            reportProgress: this.options.reportProgress || false
          },
        };
  1. In util.ts in link-http-common remove reportProgress: false from create httpClient request.

Could you please look through and give your opinion?

Thanks.

artem-galas avatar Jun 03 '19 09:06 artem-galas

If it's disabled by default then sure, let's do it. Make sure user can enable/disable not only in Link's config but also through operation's context.

kamilkisiela avatar Jun 14 '19 13:06 kamilkisiela

I've faced with two minor issues, that I don't know how to solve correct.

  1. Issue with types - compiler complains and want 'body' into observe variable
  2. Issue with testing.

Since in tests execute method are used (that come from appolo-link package) that method not using my local code, so I don't get HttpEvent response, I guess.

@kamilkisiela Could give me piece of advice? And Could you please explain what do you mean:

but also through operation's context.

What is operation's context?

Thanks.

artem-galas avatar Jun 17 '19 12:06 artem-galas

@artem-galas https://github.com/artem-galas/apollo-angular/pull/1

I'm interested how you will ship the progress value to the consumer. Apollo.query and Apollo.watchQuery both resolve with Observable<ApolloQueryResult>.

kamilkisiela avatar Jun 18 '19 19:06 kamilkisiela

@kamilkisiela Thanks for your help.

Yes, I'm also interested how to deliver that functionality to consumer....

I'm thinking to make reportProgress work we have to patch apollo-link / apollo-client packages, but I'm not sure it's a good Idea, because these packages are really significant and we can not change them for angular needs :)

What do you think?

artem-galas avatar Jun 22 '19 07:06 artem-galas

@artem-galas Maybe a directive (let's say @http) inside of graphql operation? We can't break the interface of GraphQL Result.

Can I ask why you guys need to access this http progress thing? Can't that be done within http interception?

kamilkisiela avatar Jun 22 '19 12:06 kamilkisiela

@kamilkisiela

To be honest I hardly ever use reportProgress it might be useful when download/upload files and these operations dosen't not required GraphQL. But might be for some heavy query it might be useful as well. But in that case it much more easy to implement it through the interceptor

Regarding directive @http inside graphQl operation, do you mean something like?

qpl
  @http
  heroes {
    name
 }

artem-galas avatar Jun 22 '19 13:06 artem-galas

I would really like to have this option without a "hack", but in this case I had to use rest.

leonetosoft avatar Feb 20 '20 02:02 leonetosoft

I would also like to have this option. In our application we upload files that have 1GB. We use https://github.com/jaydenseric/graphql-multipart-request-spec for this together with apollo-upload-client but I use the interceptor "the hacky way" to track progress.

gsolecki avatar Mar 04 '20 21:03 gsolecki

For those who want to be able to get the upload progress of files to their GraphQL endpoint yet don't want to hack around with apollo-upload-client, my solution was to simply reimplement the upload mutation using Angular's HttpClient with this helpful article.

Something like this:

import { HttpClient, HttpEventType, HttpResponse } from '@angular/common/http';
import { FetchResult } from '@apollo/client/core';
import { Apollo } from 'apollo-angular';
import { print } from 'graphql';
import { from, throwError } from 'rxjs';
import { filter, map, switchMap, tap } from 'rxjs/operators';
import { MutationError, UploadFileGQL, UploadFileMutation } from 'src/graphql';

const formData = new FormData();
formData.append(
'operations',
JSON.stringify({
  query: print(this.uploadFileGql.document),
  variables: {
    file: null,
  },
}),
);
formData.append(
'map',
JSON.stringify({
  file: ['variables.file'],
}),
);
formData.append('file', file, file.name);

this.http
.post('/graphql', formData, {
  reportProgress: true,
  observe: 'events',
})
.pipe(
  tap((event) => {
    if (event.type === HttpEventType.UploadProgress) {
      // You can get the upload progress here!
      console.log(Math.round((100 * event.loaded) / event.total!));
    }
  }),
  filter((event) => event.type === HttpEventType.Response),
  switchMap((event) => {
    const body: FetchResult<UploadFileMutation> = (<HttpResponse<any>>event).body!;

    if (!body.errors) {
      // This query refetching is optional and is only available in Apollo client 3.4+.
      return from(this.apollo.client.refetchQueries(['SomeQueriesToRefetch'])).pipe(map(() => body));
    } else {
      return throwError(body.errors);
    }
  }),
)
.subscribe(
  ({ data }: FetchResult<UploadFileMutation>) => {
  },
);

CDDelta avatar Mar 13 '21 12:03 CDDelta

Any update on this? :/

directcuteo avatar Nov 03 '22 11:11 directcuteo