UNPKG

3.16 kBJavaScriptView Raw
1import $$observable from 'symbol-observable'
2
3const encodeParams = params => Object.keys(params).map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k])).join('&')
4
5const buildUrl = (url, params) => params ? url + '?' + encodeParams(params) : url
6
7const fromResponseHeaderString = (headersString) => {
8 const headers = {}
9 headersString.split('\n').forEach(line => {
10 const index = line.indexOf(':')
11 if (index > 0) headers[line.slice(0, index)] = line.slice(index + 1).trim()
12 })
13 return headers
14}
15
16const noop = () => {}
17
18const rxhr = options => {
19 return {
20 subscribe (onNext, onError, onComplete) {
21 let observer = onNext
22 let request = new XMLHttpRequest()
23 if (typeof onNext === 'function') {
24 observer = {
25 next: onNext,
26 error: onError || noop,
27 complete: onComplete || noop
28 }
29 }
30 try {
31 const buildResponse = (err) => {
32 const body = err || (!options.responseType || options.responseType === 'text' ? request.responseText : request.response)
33 let response = {
34 // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
35 status: request.status === 1223 ? 204 : request.status,
36 ok: request.status >= 200 && request.status < 300,
37 type: err ? 'error' : 'default',
38 statusText: err ? request.statusText : (request.statusText || 'OK'),
39 headers: fromResponseHeaderString(request.getAllResponseHeaders()),
40 url: request.responseURL,
41 text: () => typeof body === 'object' ? JSON.stringify(body) : body,
42 json: () => typeof body === 'string' ? JSON.parse(body) : body,
43 blob: () => new Blob([body])
44 }
45 return response
46 }
47 const onReqLoad = () => {
48 let response = buildResponse()
49 if (response.ok) {
50 observer.next(response)
51 observer.complete()
52 return
53 }
54 observer.error(response)
55 }
56
57 const onReqError = () => {
58 const response = buildResponse(new Error('Network Error'))
59 observer.error(response)
60 }
61
62 const onReqTimeout = () => {
63 const response = buildResponse(new Error('ECONNABORTED'))
64 observer.error(response)
65 }
66
67 request.open(options.method.toUpperCase(), buildUrl(options.url, options.params))
68 // response type
69 options.responseType && (request.responseType = options.responseType)
70 // with credentials
71 request.withCredentials = options.withCredentials === true
72 // headers
73 for (let i in options.headers) request.setRequestHeader(i, options.headers[i])
74 // timeout in ms
75 request.timeout = options.timeout
76
77 request.send(options.body || null)
78
79 request.onload = onReqLoad
80 request.onerror = onReqError
81 request.ontimeout = onReqTimeout
82 } catch (err) {
83 observer.error(err)
84 }
85 return {
86 unsubscribe () {
87 request.abort()
88 }
89 }
90 },
91 [$$observable] () {
92 return this
93 }
94 }
95}
96
97export default rxhr