aboutsummaryrefslogtreecommitdiffstats
path: root/src/stores/lib/Request.ts
diff options
context:
space:
mode:
authorLibravatar muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com>2022-11-17 05:45:39 +0530
committerLibravatar GitHub <noreply@github.com>2022-11-17 00:15:39 +0000
commitd9502c7516bc2d4ae467c6ea8a2e4816b0885f37 (patch)
treeb339c587a5529ac26d52cfc12d9972a8a00255e6 /src/stores/lib/Request.ts
parentTransform JSX components to TSX (#755) (diff)
downloadferdium-app-d9502c7516bc2d4ae467c6ea8a2e4816b0885f37.tar.gz
ferdium-app-d9502c7516bc2d4ae467c6ea8a2e4816b0885f37.tar.zst
ferdium-app-d9502c7516bc2d4ae467c6ea8a2e4816b0885f37.zip
Transfrom workspace components to ts (#775)
Diffstat (limited to 'src/stores/lib/Request.ts')
-rw-r--r--src/stores/lib/Request.ts159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/stores/lib/Request.ts b/src/stores/lib/Request.ts
new file mode 100644
index 000000000..f9424ac99
--- /dev/null
+++ b/src/stores/lib/Request.ts
@@ -0,0 +1,159 @@
1import { observable, action, computed, makeObservable } from 'mobx';
2import { isEqual } from 'lodash/fp';
3
4type Hook = (request: Request) => void;
5
6export default class Request {
7 static _hooks: Hook[] = [];
8
9 static registerHook(hook: Hook) {
10 Request._hooks.push(hook);
11 }
12
13 @observable result: any = null;
14
15 @observable error: any = null;
16
17 @observable isExecuting = false;
18
19 @observable isError = false;
20
21 @observable wasExecuted = false;
22
23 promise: any = Promise;
24
25 protected api: any = {};
26
27 method = '';
28
29 protected isWaitingForResponse = false;
30
31 protected currentApiCall: any = null;
32
33 retry = () => this.reload();
34
35 reset = () => this._reset();
36
37 constructor(api, method) {
38 makeObservable(this);
39
40 this.api = api;
41 this.method = method;
42 }
43
44 @action _reset(): this {
45 this.error = null;
46 this.result = null;
47 this.isExecuting = false;
48 this.isError = false;
49 this.wasExecuted = false;
50 this.isWaitingForResponse = false;
51 this.promise = Promise;
52
53 return this;
54 }
55
56 execute(...callArgs: any[]): this {
57 // Do not continue if this request is already loading
58 if (this.isWaitingForResponse) return this;
59
60 if (!this.api[this.method]) {
61 throw new Error(
62 `Missing method <${this.method}> on api object:`,
63 this.api,
64 );
65 }
66
67 // This timeout is necessary to avoid warnings from mobx
68 // regarding triggering actions as side-effect of getters
69 setTimeout(
70 action(() => {
71 this.isExecuting = true;
72 }),
73 0,
74 );
75
76 // Issue api call & save it as promise that is handled to update the results of the operation
77 this.promise = new Promise((resolve, reject) => {
78 this.api[this.method](...callArgs)
79 .then(result => {
80 setTimeout(
81 action(() => {
82 this.error = null;
83 this.result = result;
84 if (this.currentApiCall) this.currentApiCall.result = result;
85 this.isExecuting = false;
86 this.isError = false;
87 this.wasExecuted = true;
88 this.isWaitingForResponse = false;
89 this._triggerHooks();
90 resolve(result);
91 }),
92 1,
93 );
94 return result;
95 })
96 .catch(
97 action(error => {
98 setTimeout(
99 action(() => {
100 this.error = error;
101 this.isExecuting = false;
102 this.isError = true;
103 this.wasExecuted = true;
104 this.isWaitingForResponse = false;
105 this._triggerHooks();
106 reject(error);
107 }),
108 1,
109 );
110 }),
111 );
112 });
113
114 this.isWaitingForResponse = true;
115 this.currentApiCall = { args: callArgs, result: null };
116 return this;
117 }
118
119 reload(): this {
120 const args = this.currentApiCall ? this.currentApiCall.args : [];
121 this.error = null;
122 return this.execute(...args);
123 }
124
125 isExecutingWithArgs(...args: any[]): boolean {
126 return (
127 this.isExecuting &&
128 this.currentApiCall &&
129 isEqual(this.currentApiCall.args, args)
130 );
131 }
132
133 @computed get isExecutingFirstTime(): boolean {
134 return !this.wasExecuted && this.isExecuting;
135 }
136
137 /* eslint-disable unicorn/no-thenable */
138 then(...args: any[]) {
139 if (!this.promise)
140 throw new Error(
141 'You have to call Request::execute before you can access it as promise',
142 );
143 return this.promise.then(...args);
144 }
145
146 catch(...args: any[]) {
147 if (!this.promise)
148 throw new Error(
149 'You have to call Request::execute before you can access it as promise',
150 );
151 return this.promise.catch(...args);
152 }
153
154 _triggerHooks(): void {
155 for (const hook of Request._hooks) {
156 hook(this);
157 }
158 }
159}