-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhttp-request.js
89 lines (76 loc) · 2.68 KB
/
http-request.js
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
const attr = (el, attr)=> el.getAttribute(attr);
export class HttpRequestElement extends HTMLElement
{
static observedAttributes =
[ 'value' // populated from localStorage, if defined initially, sets the value in storage
, 'slice'
, 'url'
, 'method'
, 'header-accept'
];
get requestHeaders()
{ const ret = {};
[...this.attributes].filter(a=>a.name.startsWith('header-')).map( a => ret[a.name.substring(7)] = a.value );
return ret
}
get requestProps()
{ const ret = {};
[...this.attributes].filter(a=>!a.name.startsWith('header-'))
.filter(a=>!a.name.startsWith('slice')).map( a => ret[a.name] = a.value );
return ret
}
disconnectedCallback(){ this.#destroy?.(); }
connectedCallback()
{
setTimeout(()=>this.fetch(),0)
}
#inProgressUrl = ''
#destroy = ()=>{}
async fetch()
{
if( !this.closest('body') )
return;
const url = attr(this, 'url') || '';
if( !url )
{ this.#destroy?.();
return this.value = {};
}
if( this.#inProgressUrl === url )
return ;
this.#inProgressUrl = url;
const controller = new AbortController();
this.#destroy = ()=> { controller.abort(this.localName+' disconnected'); this.#inProgressUrl = ''; }
const request = { ...this.requestProps, headers: this.requestHeaders }
, slice = { request }
, update = () => this.dispatchEvent( new Event('change') );
this.value = slice;
update();
const response = await fetch(url,{ ...this.requestProps, signal: controller.signal, headers: this.requestHeaders })
, r = {headers: {}};
[...response.headers].map( ([k,v]) => r.headers[k] = v );
'ok,status,statusText,type,url,redirected'.split(',').map( k=> r[k] = response[k] )
slice.response = r;
update();
if( r.headers['content-type']?.includes('json'))
try
{ slice.data = await response.json();
update();
}catch(_e){}
}
attributeChangedCallback(name, oldValue, newValue)
{ if( name === 'url' )
{ if( oldValue !== newValue)
{
oldValue && this.#destroy?.();
if( newValue )
setTimeout(()=>this.fetch(),10)
else
{ this.value = {}
setTimeout(()=>this.dispatchEvent( new Event('change') ),10)
}
}
}
}
}
window.customElements.define( 'http-request', HttpRequestElement );
export default HttpRequestElement;