91 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| export const fetchMixin = function(superClass) {
 | |
|   return class extends superClass {
 | |
|     constructor() {
 | |
|       super();
 | |
|       this.__abortControllers = new Map();
 | |
|     }
 | |
| 
 | |
|     get(url, overwrite = true) {
 | |
|       return this.do('GET', url, null, overwrite);
 | |
|     }
 | |
| 
 | |
|     head(url) {
 | |
|       return fetch(url, { method: 'HEAD' });
 | |
|     }
 | |
| 
 | |
|     post(url, data, overwrite = true) {
 | |
|       return this.do('POST', url, data, overwrite);
 | |
|     }
 | |
| 
 | |
|     async do(method, url, data, overwrite = true) {
 | |
|       this.__cancelRunningRequest(method, url);
 | |
| 
 | |
|       if (overwrite === true) {
 | |
|         const ac = new AbortController();
 | |
|         this.__abortControllers.set(`${method}:${url}`, ac);
 | |
|       }
 | |
| 
 | |
|       let statusCode = null;
 | |
|       try {
 | |
|         const reqOptions = {
 | |
|           method,
 | |
|           signal: overwrite ? this.__abortControllers.get(`${method}:${url}`).signal : null,
 | |
|           mode: 'cors',
 | |
|           cache: 'no-cache',
 | |
|           headers: {
 | |
|             'Content-Type': 'application/json; charset=utf-8'
 | |
|           },
 | |
|           referrer: 'no-referrer',
 | |
|           body: data ? JSON.stringify(data) : undefined
 | |
|         };
 | |
| 
 | |
|         document.dispatchEvent(new CustomEvent('before-request', { detail: reqOptions, bubbles: true, composed: true }));
 | |
| 
 | |
|         const resp = await fetch(url, reqOptions);
 | |
|         this.__abortControllers.delete(`${method}:${url}`);
 | |
|         if (resp.status === 500) {
 | |
|           console.error(resp);
 | |
|         }
 | |
| 
 | |
|         statusCode = resp.status;
 | |
|         if (resp.status !== 200) {
 | |
|           document.dispatchEvent(new CustomEvent('request-error', { detail: resp, bubbles: true, composed: true }));
 | |
|           return { statusCode };
 | |
|         }
 | |
| 
 | |
|         return await resp.json();
 | |
|       } catch (err) {
 | |
|         if (err.name === 'AbortError') {
 | |
|           return { statusCode: -1, error: err };
 | |
|         } else {
 | |
|           this.__abortControllers.delete(`${method}:${url}`);
 | |
| 
 | |
|           if (statusCode === null) {
 | |
|             document.dispatchEvent(new CustomEvent('request-failure', { detail: err, bubbles: true, composed: true }));
 | |
|           }
 | |
| 
 | |
|           return { statusCode, error: err };
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     isInFlight(method, url) {
 | |
|       if (url === undefined) {
 | |
|         console.error('Missing url parameter');
 | |
|         return false;
 | |
|       }
 | |
| 
 | |
|       return Boolean(this.__abortControllers.get(`${method}:${url}`));
 | |
|     }
 | |
| 
 | |
|     __cancelRunningRequest(method, url) {
 | |
|       if (this.__abortControllers.has(`${method}:${url}`)) {
 | |
|         try {
 | |
|           this.__abortControllers.get(`${method}:${url}`).abort();
 | |
|         } catch (err) { }
 | |
|         this.__abortControllers.delete(`${method}:${url}`);
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| };
 |