/ajax/libs/fetch/0.2.0/fetch.js

https://gitlab.com/Mirros/cdnjs · JavaScript · 218 lines · 180 code · 36 blank · 2 comment · 14 complexity · 5ca7636d931dc45264642bda3ce269db MD5 · raw file

  1. (function() {
  2. 'use strict';
  3. if (window.fetch) {
  4. return
  5. }
  6. function Headers(headers) {
  7. this.map = {}
  8. var self = this
  9. if (headers instanceof Headers) {
  10. headers.forEach(function(name, values) {
  11. values.forEach(function(value) {
  12. self.append(name, value)
  13. })
  14. })
  15. } else if (headers) {
  16. Object.getOwnPropertyNames(headers).forEach(function(name) {
  17. self.append(name, headers[name])
  18. })
  19. }
  20. }
  21. Headers.prototype.append = function(name, value) {
  22. var list = this.map[name]
  23. if (!list) {
  24. list = []
  25. this.map[name] = list
  26. }
  27. list.push(value)
  28. }
  29. Headers.prototype.delete = function(name) {
  30. delete this.map[name]
  31. }
  32. Headers.prototype.get = function(name) {
  33. var values = this.map[name]
  34. return values ? values[0] : null
  35. }
  36. Headers.prototype.getAll = function(name) {
  37. return this.map[name] || []
  38. }
  39. Headers.prototype.has = function(name) {
  40. return this.map.hasOwnProperty(name)
  41. }
  42. Headers.prototype.set = function(name, value) {
  43. this.map[name] = [value]
  44. }
  45. // Instead of iterable for now.
  46. Headers.prototype.forEach = function(callback) {
  47. var self = this
  48. Object.getOwnPropertyNames(this.map).forEach(function(name) {
  49. callback(name, self.map[name])
  50. })
  51. }
  52. function consumed(body) {
  53. if (body.bodyUsed) {
  54. return new Promise.reject(new TypeError('Body already consumed'))
  55. }
  56. body.bodyUsed = true
  57. }
  58. function Body() {
  59. this.body = null
  60. this.bodyUsed = false
  61. this.arrayBuffer = function() {
  62. throw new Error('Not implemented yet')
  63. }
  64. this.blob = function() {
  65. var rejected = consumed(this)
  66. return rejected ? rejected : Promise.resolve(new Blob([this.body]))
  67. }
  68. this.formData = function() {
  69. return Promise.resolve(decode(this.body))
  70. }
  71. this.json = function() {
  72. var rejected = consumed(this)
  73. if (rejected) {
  74. return rejected
  75. }
  76. var body = this.body
  77. return new Promise(function(resolve, reject) {
  78. try {
  79. resolve(JSON.parse(body))
  80. } catch (ex) {
  81. reject(ex)
  82. }
  83. })
  84. }
  85. this.text = function() {
  86. var rejected = consumed(this)
  87. return rejected ? rejected : Promise.resolve(this.body)
  88. }
  89. return this
  90. }
  91. function Request(url, options) {
  92. options = options || {}
  93. this.url = url
  94. this.body = options.body
  95. this.credentials = options.credentials || null
  96. this.headers = new Headers(options.headers)
  97. this.method = options.method || 'GET'
  98. this.mode = options.mode || null
  99. this.referrer = null
  100. }
  101. function encode(params) {
  102. return Object.getOwnPropertyNames(params).filter(function(name) {
  103. return params[name] !== undefined
  104. }).map(function(name) {
  105. var value = (params[name] === null) ? '' : params[name]
  106. return encodeURIComponent(name) + '=' + encodeURIComponent(value)
  107. }).join('&').replace(/%20/g, '+')
  108. }
  109. function decode(body) {
  110. var form = new FormData()
  111. body.trim().split('&').forEach(function(bytes) {
  112. if (bytes) {
  113. var split = bytes.split('=')
  114. var name = split.shift().replace(/\+/g, ' ')
  115. var value = split.join('=').replace(/\+/g, ' ')
  116. form.append(decodeURIComponent(name), decodeURIComponent(value))
  117. }
  118. })
  119. return form
  120. }
  121. function isObject(value) {
  122. try {
  123. return Object.getPrototypeOf(value) === Object.prototype
  124. } catch (ex) {
  125. // Probably a string literal.
  126. return false
  127. }
  128. }
  129. function headers(xhr) {
  130. var head = new Headers()
  131. var pairs = xhr.getAllResponseHeaders().trim().split('\n')
  132. pairs.forEach(function(header) {
  133. var split = header.trim().split(':')
  134. var key = split.shift().trim()
  135. var value = split.join(':').trim()
  136. head.append(key, value)
  137. })
  138. return head
  139. }
  140. Request.prototype.fetch = function() {
  141. var self = this
  142. return new Promise(function(resolve, reject) {
  143. var xhr = new XMLHttpRequest()
  144. xhr.onload = function() {
  145. var options = {
  146. status: xhr.status,
  147. statusText: xhr.statusText,
  148. headers: headers(xhr)
  149. }
  150. resolve(new Response(xhr.responseText, options))
  151. }
  152. xhr.onerror = function() {
  153. reject()
  154. }
  155. xhr.open(self.method, self.url)
  156. self.headers.forEach(function(name, values) {
  157. values.forEach(function(value) {
  158. xhr.setRequestHeader(name, value)
  159. })
  160. })
  161. var body = self.body
  162. if (isObject(self.body)) {
  163. xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
  164. body = encode(self.body)
  165. }
  166. xhr.send(body)
  167. })
  168. }
  169. Body.call(Request.prototype)
  170. function Response(body, options) {
  171. this.body = body
  172. this.type = 'default'
  173. this.url = null
  174. this.status = options.status
  175. this.statusText = options.statusText
  176. this.headers = options.headers
  177. }
  178. Body.call(Response.prototype)
  179. window.fetch = function (url, options) {
  180. return new Request(url, options).fetch()
  181. }
  182. })()