httpRequest.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /**
  2. * @enum{string}
  3. **/
  4. var HttpRequestMethod = {
  5. GET: "GET",
  6. POST: "POST",
  7. PUT: "PUT",
  8. DELETE: "DELETE"
  9. };
  10. /**
  11. * @enum{string}
  12. **/
  13. var HttpRequestResponseType = {
  14. ARRAYBUFFER: "arraybuffer",
  15. BLOB: "blob",
  16. DOCUMENT: "document",
  17. JSON: "json",
  18. TEXT: "text"
  19. };
  20. /**
  21. * @abstract
  22. * @constructor
  23. * @param {HttpRequestMethod|string} urlOrMethod url or method to use (default: GET)
  24. * @param {string=} url
  25. **/
  26. function HttpRequest(urlOrMethod, url) {
  27. /** @const @type {string} */
  28. this.url = url || urlOrMethod;
  29. /** @const @type {HttpRequestMethod} */
  30. this.method = url ? /** @type {HttpRequestMethod} */ (urlOrMethod) : HttpRequestMethod.GET;
  31. /** @type {Array<function(number, string, *)>|undefined} */
  32. this._callback;
  33. /** @type {Array<function(number, string, *)>|undefined} */
  34. this._callbackError;
  35. /** @type {Array<function(number, string, *)>|undefined} */
  36. this._callbackSuccess;
  37. }
  38. /**
  39. * @param {Array<function(number, string, *)>|undefined} callbacks
  40. * @param {number} statusCode
  41. * @param {string} statusText
  42. * @param {*} response
  43. **/
  44. HttpRequest.fireCallbacks = function(callbacks, statusCode, statusText, response) {
  45. if (callbacks)
  46. callbacks.forEach(function(cb) {
  47. cb(statusCode, statusText, response);
  48. });
  49. };
  50. /**
  51. * @param {function(number, string, (string|Object|null))} cb callback (statusCode statusText responseText)
  52. * @param {Object=} ctx
  53. * @return {HttpRequest}
  54. **/
  55. HttpRequest.prototype.callback = function(cb, ctx) {
  56. if (!this._callback)
  57. this._callback = [];
  58. cb.bind(ctx || this);
  59. this._callback.push(cb);
  60. return this;
  61. };
  62. /**
  63. * @param {function(number, string, (string|Object|null))} cb callback (statusCode statusText responseText)
  64. * @param {Object=} ctx
  65. * @return {HttpRequest}
  66. **/
  67. HttpRequest.prototype.callbackSuccess = function(cb, ctx) {
  68. if (!this._callbackSuccess)
  69. this._callbackSuccess = [];
  70. cb.bind(ctx || this);
  71. this._callbackSuccess.push(cb);
  72. return this;
  73. };
  74. /**
  75. * @param {function(number, string, (string|Object|null))} cb callback (statusCode statusText responseText)
  76. * @param {Object=} ctx
  77. * @return {HttpRequest}
  78. **/
  79. HttpRequest.prototype.callbackError = function(cb, ctx) {
  80. if (!this._callbackError)
  81. this._callbackError = [];
  82. cb.bind(ctx || this);
  83. this._callbackError.push(cb);
  84. return this;
  85. };
  86. /**
  87. * @abstract
  88. * @param {number} timeo
  89. * @return {HttpRequest}
  90. **/
  91. HttpRequest.prototype.setTimeout = function(timeo) {};
  92. /**
  93. * @abstract
  94. * @param {HttpRequestResponseType} respType
  95. * @return {HttpRequest}
  96. **/
  97. HttpRequest.prototype.setResponseType = function(respType) {};
  98. /**
  99. * @abstract
  100. * @param {string|FormData=} payload
  101. * @return {HttpRequest}
  102. **/
  103. HttpRequest.prototype.send = function(payload) {};
  104. /**
  105. * @constructor
  106. * @extends {HttpRequest}
  107. * @param {HttpRequestMethod|string} urlOrMethod url or method to use (default: GET)
  108. * @param {string=} url
  109. **/
  110. function XHRHttpRequest(urlOrMethod, url) {
  111. HttpRequest.call(this, urlOrMethod, url);
  112. /** @const @type {XMLHttpRequest} */
  113. this.xhr = new XMLHttpRequest();
  114. this.xhr.onreadystatechange = (function(e) {
  115. if (this.xhr.readyState === 4) {
  116. if (Math.floor(this.xhr.status / 100) === 2) {
  117. HttpRequest.fireCallbacks(this._callbackSuccess, this.xhr.status, this.xhr.statusText, this.xhr.response);
  118. } else {
  119. HttpRequest.fireCallbacks(this._callbackError, this.xhr.status, this.xhr.statusText, this.xhr.response);
  120. }
  121. HttpRequest.fireCallbacks(this._callback, this.xhr.status, this.xhr.statusText, this.xhr.response);
  122. }
  123. }).bind(this);
  124. }
  125. XHRHttpRequest.prototype = Object.create(HttpRequest.prototype);
  126. XHRHttpRequest.prototype.constructor = XHRHttpRequest;
  127. /**
  128. * @param {number} timeo
  129. * @return {HttpRequest}
  130. **/
  131. XHRHttpRequest.prototype.setTimeout = function(timeo) {
  132. this.xhr.timeout = timeo;
  133. return this;
  134. };
  135. /**
  136. * @param {HttpRequestResponseType} respType
  137. * @return {HttpRequest}
  138. **/
  139. XHRHttpRequest.prototype.setResponseType = function(respType) {
  140. this.xhr.responseType = respType;
  141. return this;
  142. };
  143. /**
  144. * @param {string|FormData=} payload
  145. * @return {HttpRequest}
  146. **/
  147. XHRHttpRequest.prototype.send = function(payload) {
  148. this.xhr.open(this.method, this.url, true);
  149. this.xhr.send(payload);
  150. return this;
  151. };
  152. /**
  153. * @constructor
  154. * @extends {HttpRequest}
  155. * @param {HttpRequestMethod|string} urlOrMethod url or method to use (default: GET)
  156. * @param {string=} url
  157. **/
  158. function NativeHttpRequest(urlOrMethod, url) {
  159. HttpRequest.call(this, urlOrMethod, url);
  160. /** @type {number} */
  161. this.timeo = 5000;
  162. /** @type {HttpRequestResponseType} */
  163. this.responseType = HttpRequestResponseType.TEXT;
  164. }
  165. NativeHttpRequest.prototype = Object.create(HttpRequest.prototype);
  166. NativeHttpRequest.prototype.constructor = XHRHttpRequest;
  167. /**
  168. * @param {number} timeo
  169. * @return {HttpRequest}
  170. **/
  171. NativeHttpRequest.prototype.setTimeout = function(timeo) {
  172. this.timeo = timeo;
  173. return this;
  174. };
  175. /**
  176. * @param {HttpRequestResponseType} respType
  177. * @return {HttpRequest}
  178. **/
  179. NativeHttpRequest.prototype.setResponseType = function(respType) {
  180. this.responseType = respType;
  181. return this;
  182. };
  183. /**
  184. * @param {string|FormData=} payload
  185. * @return {string|null}
  186. **/
  187. NativeHttpRequest.prototype.stringifyPayload = function(payload) {
  188. if (!payload) return null;
  189. if (typeof payload === "string") return payload;
  190. var obj = {};
  191. for (var i in payload)
  192. obj[i] = payload[i];
  193. return JSON.stringify(obj);
  194. };
  195. /** @type {function(string):string} */
  196. NativeHttpRequest.makeAbsoluteUrl = (function() {
  197. var a = document.createElement('a');
  198. return function(link) {
  199. a.href = link;
  200. return a.href;
  201. };
  202. })();
  203. /**
  204. * @param {string|FormData=} payload
  205. * @return {HttpRequest}
  206. **/
  207. NativeHttpRequest.prototype.send = function(payload) {
  208. __native.sendHttpRequest(this.method, NativeHttpRequest.makeAbsoluteUrl(this.url), this.timeo, this.responseType, this.stringifyPayload(payload), CALLBACK.makeCallback(function(statusCode, statusText, respText) {
  209. var resp;
  210. try {
  211. resp = this.responseType === HttpRequestResponseType.TEXT ? respText : JSON.parse(respText);
  212. } catch (e) {
  213. resp = respText;
  214. }
  215. if (__native.isDebug())
  216. console.log(this, {
  217. statusCode: statusCode,
  218. statusText: statusText,
  219. resp: respText
  220. });
  221. if (Math.floor(statusCode / 100) === 2) {
  222. HttpRequest.fireCallbacks(this._callbackSuccess, statusCode, statusText, resp);
  223. } else {
  224. HttpRequest.fireCallbacks(this._callbackError, statusCode, statusText, resp);
  225. }
  226. HttpRequest.fireCallbacks(this._callback, statusCode, statusText, resp);
  227. }, this));
  228. return this;
  229. };
  230. /**
  231. * @param {HttpRequestMethod|string} urlOrMethod
  232. * @param {string=} url
  233. * @return {HttpRequest}
  234. **/
  235. function HttpRequestWrapper(urlOrMethod, url) {
  236. return isNative() ? new NativeHttpRequest(urlOrMethod, url) : new XHRHttpRequest(urlOrMethod, url);
  237. }