-
Notifications
You must be signed in to change notification settings - Fork 536
Expand file tree
/
Copy pathrequest.effects.ts
More file actions
102 lines (96 loc) · 3.69 KB
/
request.effects.ts
File metadata and controls
102 lines (96 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import {
Injectable,
Injector,
} from '@angular/core';
import { RestRequestMethod } from '@dspace/config/rest-request-method';
import {
hasValue,
isNotEmpty,
} from '@dspace/shared/utils/empty.util';
import {
Actions,
createEffect,
ofType,
} from '@ngrx/effects';
import {
catchError,
filter,
map,
mergeMap,
take,
withLatestFrom,
} from 'rxjs/operators';
import { getClassForType } from '../cache/builders/build-decorators';
import { ParsedResponse } from '../cache/response.models';
import { DSpaceSerializer } from '../dspace-rest/dspace.serializer';
import { DspaceRestService } from '../dspace-rest/dspace-rest.service';
import { RawRestResponse } from '../dspace-rest/raw-rest-response.model';
import { StoreActionTypes } from '../ngrx/type';
import { XSRFService } from '../xsrf/xsrf.service';
import {
RequestActionTypes,
RequestErrorAction,
RequestExecuteAction,
RequestSuccessAction,
ResetResponseTimestampsAction,
} from './request.actions';
import { RequestService } from './request.service';
import { RequestEntry } from './request-entry.model';
import { RequestError } from './request-error.model';
import { RestRequestWithResponseParser } from './rest-request-with-response-parser.model';
@Injectable()
export class RequestEffects {
execute = createEffect(() => this.actions$.pipe(
ofType(RequestActionTypes.EXECUTE),
mergeMap((action: RequestExecuteAction) => {
return this.requestService.getByUUID(action.payload).pipe(
take(1),
);
}),
filter((entry: RequestEntry) => hasValue(entry)),
withLatestFrom(this.xsrfService.tokenInitialized$),
// If it's a GET request, or we have an XSRF token, dispatch it immediately
// Otherwise wait for the XSRF token first
filter(([entry, tokenInitialized]: [RequestEntry, boolean]) => entry.request.method === RestRequestMethod.GET || tokenInitialized === true),
map(([entry, tokenInitialized]: [RequestEntry, boolean]) => entry.request),
mergeMap((request: RestRequestWithResponseParser) => {
let body = request.body;
if (isNotEmpty(request.body) && !request.isMultipart) {
const serializer = new DSpaceSerializer(getClassForType(request.body.type));
body = serializer.serialize(request.body);
}
return this.restApi.request(request.method, request.href, body, request.options, request.isMultipart).pipe(
map((data: RawRestResponse) => this.injector.get(request.getResponseParser()).parse(request, data)),
map((response: ParsedResponse) => new RequestSuccessAction(request.uuid, response.statusCode, response.link, response.unCacheableObject)),
catchError((error: unknown) => {
if (error instanceof RequestError) {
// if it's an error returned by the server, complete the request
return [new RequestErrorAction(request.uuid, error.statusCode, error.message, error.errors)];
} else {
// if it's a client side error, throw it
throw error;
}
}),
);
}),
));
/**
* When the store is rehydrated in the browser, set all cache
* timestamps to 'now', because the time zone of the server can
* differ from the client.
*
* This assumes that the server cached everything a negligible
* time ago, and will likely need to be revisited later
*/
fixTimestampsOnRehydrate = createEffect(() => this.actions$
.pipe(ofType(StoreActionTypes.REHYDRATE),
map(() => new ResetResponseTimestampsAction(new Date().getTime())),
));
constructor(
private actions$: Actions,
private restApi: DspaceRestService,
private injector: Injector,
protected requestService: RequestService,
protected xsrfService: XSRFService,
) { }
}