Blame view

node_modules/xhr/index.js 7 KB
2a09d1a4   liuqimichale   添加宜春 天水 宣化
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  "use strict";
  var window = require("global/window")
  var isFunction = require("is-function")
  var parseHeaders = require("parse-headers")
  var xtend = require("xtend")
  
  module.exports = createXHR
  createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
  createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest
  
  forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
      createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
          options = initParams(uri, options, callback)
          options.method = method.toUpperCase()
          return _createXHR(options)
      }
  })
  
  function forEachArray(array, iterator) {
      for (var i = 0; i < array.length; i++) {
          iterator(array[i])
      }
  }
  
  function isEmpty(obj){
      for(var i in obj){
          if(obj.hasOwnProperty(i)) return false
      }
      return true
  }
  
  function initParams(uri, options, callback) {
      var params = uri
  
      if (isFunction(options)) {
          callback = options
          if (typeof uri === "string") {
              params = {uri:uri}
          }
      } else {
          params = xtend(options, {uri: uri})
      }
  
      params.callback = callback
      return params
  }
  
  function createXHR(uri, options, callback) {
      options = initParams(uri, options, callback)
      return _createXHR(options)
  }
  
  function _createXHR(options) {
      if(typeof options.callback === "undefined"){
          throw new Error("callback argument missing")
      }
  
      var called = false
      var callback = function cbOnce(err, response, body){
          if(!called){
              called = true
              options.callback(err, response, body)
          }
      }
  
      function readystatechange() {
          if (xhr.readyState === 4) {
              setTimeout(loadFunc, 0)
          }
      }
  
      function getBody() {
          // Chrome with requestType=blob throws errors arround when even testing access to responseText
          var body = undefined
  
          if (xhr.response) {
              body = xhr.response
          } else {
              body = xhr.responseText || getXml(xhr)
          }
  
          if (isJson) {
              try {
                  body = JSON.parse(body)
              } catch (e) {}
          }
  
          return body
      }
  
      function errorFunc(evt) {
          clearTimeout(timeoutTimer)
          if(!(evt instanceof Error)){
              evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
          }
          evt.statusCode = 0
          return callback(evt, failureResponse)
      }
  
      // will load the data & process the response in a special response object
      function loadFunc() {
          if (aborted) return
          var status
          clearTimeout(timeoutTimer)
          if(options.useXDR && xhr.status===undefined) {
              //IE8 CORS GET successful response doesn't have a status field, but body is fine
              status = 200
          } else {
              status = (xhr.status === 1223 ? 204 : xhr.status)
          }
          var response = failureResponse
          var err = null
  
          if (status !== 0){
              response = {
                  body: getBody(),
                  statusCode: status,
                  method: method,
                  headers: {},
                  url: uri,
                  rawRequest: xhr
              }
              if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
                  response.headers = parseHeaders(xhr.getAllResponseHeaders())
              }
          } else {
              err = new Error("Internal XMLHttpRequest Error")
          }
          return callback(err, response, response.body)
      }
  
      var xhr = options.xhr || null
  
      if (!xhr) {
          if (options.cors || options.useXDR) {
              xhr = new createXHR.XDomainRequest()
          }else{
              xhr = new createXHR.XMLHttpRequest()
          }
      }
  
      var key
      var aborted
      var uri = xhr.url = options.uri || options.url
      var method = xhr.method = options.method || "GET"
      var body = options.body || options.data
      var headers = xhr.headers = options.headers || {}
      var sync = !!options.sync
      var isJson = false
      var timeoutTimer
      var failureResponse = {
          body: undefined,
          headers: {},
          statusCode: 0,
          method: method,
          url: uri,
          rawRequest: xhr
      }
  
      if ("json" in options && options.json !== false) {
          isJson = true
          headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
          if (method !== "GET" && method !== "HEAD") {
              headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
              body = JSON.stringify(options.json === true ? body : options.json)
          }
      }
  
      xhr.onreadystatechange = readystatechange
      xhr.onload = loadFunc
      xhr.onerror = errorFunc
      // IE9 must have onprogress be set to a unique function.
      xhr.onprogress = function () {
          // IE must die
      }
      xhr.onabort = function(){
          aborted = true;
      }
      xhr.ontimeout = errorFunc
      xhr.open(method, uri, !sync, options.username, options.password)
      //has to be after open
      if(!sync) {
          xhr.withCredentials = !!options.withCredentials
      }
      // Cannot set timeout with sync request
      // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
      // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
      if (!sync && options.timeout > 0 ) {
          timeoutTimer = setTimeout(function(){
              if (aborted) return
              aborted = true//IE9 may still call readystatechange
              xhr.abort("timeout")
              var e = new Error("XMLHttpRequest timeout")
              e.code = "ETIMEDOUT"
              errorFunc(e)
          }, options.timeout )
      }
  
      if (xhr.setRequestHeader) {
          for(key in headers){
              if(headers.hasOwnProperty(key)){
                  xhr.setRequestHeader(key, headers[key])
              }
          }
      } else if (options.headers && !isEmpty(options.headers)) {
          throw new Error("Headers cannot be set on an XDomainRequest object")
      }
  
      if ("responseType" in options) {
          xhr.responseType = options.responseType
      }
  
      if ("beforeSend" in options &&
          typeof options.beforeSend === "function"
      ) {
          options.beforeSend(xhr)
      }
  
      // Microsoft Edge browser sends "undefined" when send is called with undefined value.
      // XMLHttpRequest spec says to pass null as body to indicate no body
      // See https://github.com/naugtur/xhr/issues/100.
      xhr.send(body || null)
  
      return xhr
  
  
  }
  
  function getXml(xhr) {
      if (xhr.responseType === "document") {
          return xhr.responseXML
      }
      var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"
      if (xhr.responseType === "" && !firefoxBugTakenEffect) {
          return xhr.responseXML
      }
  
      return null
  }
  
  function noop() {}