utils.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. 'use strict';
  2. var bind = require('./helpers/bind');
  3. /*global toString:true*/
  4. // utils is a library of generic helper functions non-specific to axios
  5. var toString = Object.prototype.toString;
  6. /**
  7. * Determine if a value is an Array
  8. *
  9. * @param {Object} val The value to test
  10. * @returns {boolean} True if value is an Array, otherwise false
  11. */
  12. function isArray(val) {
  13. return toString.call(val) === '[object Array]';
  14. }
  15. /**
  16. * Determine if a value is undefined
  17. *
  18. * @param {Object} val The value to test
  19. * @returns {boolean} True if the value is undefined, otherwise false
  20. */
  21. function isUndefined(val) {
  22. return typeof val === 'undefined';
  23. }
  24. /**
  25. * Determine if a value is a Buffer
  26. *
  27. * @param {Object} val The value to test
  28. * @returns {boolean} True if value is a Buffer, otherwise false
  29. */
  30. function isBuffer(val) {
  31. return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
  32. && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
  33. }
  34. /**
  35. * Determine if a value is an ArrayBuffer
  36. *
  37. * @param {Object} val The value to test
  38. * @returns {boolean} True if value is an ArrayBuffer, otherwise false
  39. */
  40. function isArrayBuffer(val) {
  41. return toString.call(val) === '[object ArrayBuffer]';
  42. }
  43. /**
  44. * Determine if a value is a FormData
  45. *
  46. * @param {Object} val The value to test
  47. * @returns {boolean} True if value is an FormData, otherwise false
  48. */
  49. function isFormData(val) {
  50. return (typeof FormData !== 'undefined') && (val instanceof FormData);
  51. }
  52. /**
  53. * Determine if a value is a view on an ArrayBuffer
  54. *
  55. * @param {Object} val The value to test
  56. * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
  57. */
  58. function isArrayBufferView(val) {
  59. var result;
  60. if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
  61. result = ArrayBuffer.isView(val);
  62. } else {
  63. result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
  64. }
  65. return result;
  66. }
  67. /**
  68. * Determine if a value is a String
  69. *
  70. * @param {Object} val The value to test
  71. * @returns {boolean} True if value is a String, otherwise false
  72. */
  73. function isString(val) {
  74. return typeof val === 'string';
  75. }
  76. /**
  77. * Determine if a value is a Number
  78. *
  79. * @param {Object} val The value to test
  80. * @returns {boolean} True if value is a Number, otherwise false
  81. */
  82. function isNumber(val) {
  83. return typeof val === 'number';
  84. }
  85. /**
  86. * Determine if a value is an Object
  87. *
  88. * @param {Object} val The value to test
  89. * @returns {boolean} True if value is an Object, otherwise false
  90. */
  91. function isObject(val) {
  92. return val !== null && typeof val === 'object';
  93. }
  94. /**
  95. * Determine if a value is a Date
  96. *
  97. * @param {Object} val The value to test
  98. * @returns {boolean} True if value is a Date, otherwise false
  99. */
  100. function isDate(val) {
  101. return toString.call(val) === '[object Date]';
  102. }
  103. /**
  104. * Determine if a value is a File
  105. *
  106. * @param {Object} val The value to test
  107. * @returns {boolean} True if value is a File, otherwise false
  108. */
  109. function isFile(val) {
  110. return toString.call(val) === '[object File]';
  111. }
  112. /**
  113. * Determine if a value is a Blob
  114. *
  115. * @param {Object} val The value to test
  116. * @returns {boolean} True if value is a Blob, otherwise false
  117. */
  118. function isBlob(val) {
  119. return toString.call(val) === '[object Blob]';
  120. }
  121. /**
  122. * Determine if a value is a Function
  123. *
  124. * @param {Object} val The value to test
  125. * @returns {boolean} True if value is a Function, otherwise false
  126. */
  127. function isFunction(val) {
  128. return toString.call(val) === '[object Function]';
  129. }
  130. /**
  131. * Determine if a value is a Stream
  132. *
  133. * @param {Object} val The value to test
  134. * @returns {boolean} True if value is a Stream, otherwise false
  135. */
  136. function isStream(val) {
  137. return isObject(val) && isFunction(val.pipe);
  138. }
  139. /**
  140. * Determine if a value is a URLSearchParams object
  141. *
  142. * @param {Object} val The value to test
  143. * @returns {boolean} True if value is a URLSearchParams object, otherwise false
  144. */
  145. function isURLSearchParams(val) {
  146. return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
  147. }
  148. /**
  149. * Trim excess whitespace off the beginning and end of a string
  150. *
  151. * @param {String} str The String to trim
  152. * @returns {String} The String freed of excess whitespace
  153. */
  154. function trim(str) {
  155. return str.replace(/^\s*/, '').replace(/\s*$/, '');
  156. }
  157. /**
  158. * Determine if we're running in a standard browser environment
  159. *
  160. * This allows axios to run in a web worker, and react-native.
  161. * Both environments support XMLHttpRequest, but not fully standard globals.
  162. *
  163. * web workers:
  164. * typeof window -> undefined
  165. * typeof document -> undefined
  166. *
  167. * react-native:
  168. * navigator.product -> 'ReactNative'
  169. * nativescript
  170. * navigator.product -> 'NativeScript' or 'NS'
  171. */
  172. function isStandardBrowserEnv() {
  173. if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||
  174. navigator.product === 'NativeScript' ||
  175. navigator.product === 'NS')) {
  176. return false;
  177. }
  178. return (
  179. typeof window !== 'undefined' &&
  180. typeof document !== 'undefined'
  181. );
  182. }
  183. /**
  184. * Iterate over an Array or an Object invoking a function for each item.
  185. *
  186. * If `obj` is an Array callback will be called passing
  187. * the value, index, and complete array for each item.
  188. *
  189. * If 'obj' is an Object callback will be called passing
  190. * the value, key, and complete object for each property.
  191. *
  192. * @param {Object|Array} obj The object to iterate
  193. * @param {Function} fn The callback to invoke for each item
  194. */
  195. function forEach(obj, fn) {
  196. // Don't bother if no value provided
  197. if (obj === null || typeof obj === 'undefined') {
  198. return;
  199. }
  200. // Force an array if not already something iterable
  201. if (typeof obj !== 'object') {
  202. /*eslint no-param-reassign:0*/
  203. obj = [obj];
  204. }
  205. if (isArray(obj)) {
  206. // Iterate over array values
  207. for (var i = 0, l = obj.length; i < l; i++) {
  208. fn.call(null, obj[i], i, obj);
  209. }
  210. } else {
  211. // Iterate over object keys
  212. for (var key in obj) {
  213. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  214. fn.call(null, obj[key], key, obj);
  215. }
  216. }
  217. }
  218. }
  219. /**
  220. * Accepts varargs expecting each argument to be an object, then
  221. * immutably merges the properties of each object and returns result.
  222. *
  223. * When multiple objects contain the same key the later object in
  224. * the arguments list will take precedence.
  225. *
  226. * Example:
  227. *
  228. * ```js
  229. * var result = merge({foo: 123}, {foo: 456});
  230. * console.log(result.foo); // outputs 456
  231. * ```
  232. *
  233. * @param {Object} obj1 Object to merge
  234. * @returns {Object} Result of all merge properties
  235. */
  236. function merge(/* obj1, obj2, obj3, ... */) {
  237. var result = {};
  238. function assignValue(val, key) {
  239. if (typeof result[key] === 'object' && typeof val === 'object') {
  240. result[key] = merge(result[key], val);
  241. } else {
  242. result[key] = val;
  243. }
  244. }
  245. for (var i = 0, l = arguments.length; i < l; i++) {
  246. forEach(arguments[i], assignValue);
  247. }
  248. return result;
  249. }
  250. /**
  251. * Function equal to merge with the difference being that no reference
  252. * to original objects is kept.
  253. *
  254. * @see merge
  255. * @param {Object} obj1 Object to merge
  256. * @returns {Object} Result of all merge properties
  257. */
  258. function deepMerge(/* obj1, obj2, obj3, ... */) {
  259. var result = {};
  260. function assignValue(val, key) {
  261. if (typeof result[key] === 'object' && typeof val === 'object') {
  262. result[key] = deepMerge(result[key], val);
  263. } else if (typeof val === 'object') {
  264. result[key] = deepMerge({}, val);
  265. } else {
  266. result[key] = val;
  267. }
  268. }
  269. for (var i = 0, l = arguments.length; i < l; i++) {
  270. forEach(arguments[i], assignValue);
  271. }
  272. return result;
  273. }
  274. /**
  275. * Extends object a by mutably adding to it the properties of object b.
  276. *
  277. * @param {Object} a The object to be extended
  278. * @param {Object} b The object to copy properties from
  279. * @param {Object} thisArg The object to bind function to
  280. * @return {Object} The resulting value of object a
  281. */
  282. function extend(a, b, thisArg) {
  283. forEach(b, function assignValue(val, key) {
  284. if (thisArg && typeof val === 'function') {
  285. a[key] = bind(val, thisArg);
  286. } else {
  287. a[key] = val;
  288. }
  289. });
  290. return a;
  291. }
  292. module.exports = {
  293. isArray: isArray,
  294. isArrayBuffer: isArrayBuffer,
  295. isBuffer: isBuffer,
  296. isFormData: isFormData,
  297. isArrayBufferView: isArrayBufferView,
  298. isString: isString,
  299. isNumber: isNumber,
  300. isObject: isObject,
  301. isUndefined: isUndefined,
  302. isDate: isDate,
  303. isFile: isFile,
  304. isBlob: isBlob,
  305. isFunction: isFunction,
  306. isStream: isStream,
  307. isURLSearchParams: isURLSearchParams,
  308. isStandardBrowserEnv: isStandardBrowserEnv,
  309. forEach: forEach,
  310. merge: merge,
  311. deepMerge: deepMerge,
  312. extend: extend,
  313. trim: trim
  314. };