Show:
  1. /**
  2. support ajax request in this module
  3. @module mixins
  4. @submodule ajax
  5. */
  6. import Mixin from '@ember/object/mixin';
  7. import { A, isArray } from '@ember/array';
  8. import Evented from '@ember/object/evented';
  9. import { isBlank, isNone } from '@ember/utils';
  10. import { Promise } from 'rsvp';
  11. import $ from 'jquery';
  12.  
  13. /**
  14. get request function used in ajax.request property
  15. @private
  16. */
  17. const _get = function (url, options) {
  18. let self = this.parent;
  19. return self.ajax('get', url, options).then(
  20. function (data) {
  21. // eslint-disable-next-line no-useless-catch
  22. try {
  23. return self.getSerializer(data);
  24. } catch (e) {
  25. throw e;
  26. }
  27. },
  28. function (reason) {
  29. throw reason;
  30. }
  31. );
  32. };
  33.  
  34. /**
  35. post request function used in ajax.request property
  36. @private
  37. */
  38. const _post = function (url, options) {
  39. let self = this.parent;
  40. return self.ajax('post', url, options).then(
  41. function (data) {
  42. // eslint-disable-next-line no-useless-catch
  43. try {
  44. return self.postSerializer(data);
  45. } catch (e) {
  46. throw e;
  47. }
  48. },
  49. function (reason) {
  50. throw reason;
  51. }
  52. );
  53. };
  54.  
  55. /**
  56. delete request function used in ajax.request property
  57. @private
  58. */
  59. const _delete = function (url, options) {
  60. let self = this.parent;
  61. return self.ajax('delete', url, options).then(
  62. function (data) {
  63. // eslint-disable-next-line no-useless-catch
  64. try {
  65. return self.deleteSerializer(data);
  66. } catch (e) {
  67. throw e;
  68. }
  69. },
  70. function (reason) {
  71. throw reason;
  72. }
  73. );
  74. };
  75.  
  76. /**
  77. put request function used in ajax.request property
  78. @private
  79. */
  80. const _put = function (url, options) {
  81. let self = this.parent;
  82. return self.ajax('put', url, options).then(
  83. function (data) {
  84. // eslint-disable-next-line no-useless-catch
  85. try {
  86. return self.putSerializer(data);
  87. } catch (e) {
  88. throw e;
  89. }
  90. },
  91. function (reason) {
  92. throw reason;
  93. }
  94. );
  95. };
  96.  
  97. /**
  98. wrap jquery ajax with Ember.RSVP.Promise, this mixin also has events like:
  99. - ajaxStart be trigged when ajax request start
  100. - ajaxDone be trigged when ajax request finish (success or fails)
  101. - ajaxSuccess be trigged when promise resovle success
  102. - ajaxError be trigged when ajax request fails
  103. - RESTSerializerError be trigged error happen when response data serialize
  104. @public
  105. @class ajax
  106. */
  107. export default Mixin.create(Evented, {
  108. /**
  109. wrapper all request method (get put post delete) into request object
  110. @property request
  111. @type Object
  112. @default {Object}
  113. */
  114. request: null,
  115. /**
  116. ajax request setting See http://devdocs.io/jquery/jquery.ajax
  117. @property ajaxSettings
  118. @type Object
  119. @default {dataType: 'json'}
  120. */
  121. // eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects
  122. ajaxSettings: {
  123. dataType: 'json',
  124. },
  125. /**
  126. if contentType is application/json which method request data need to be serialized with json
  127. @property needSerializedMethod
  128. @type Object
  129. @default ['post', 'put']
  130. */
  131. needSerializedMethod: null,
  132. /**
  133. jquery ajax method wrapper, return promise
  134. @method ajax
  135. @param {String} method request method
  136. @param {String} url request url
  137. @param {Object} options ajax jquery ajax settings, see http://devdocs.io/jquery/jquery.ajax
  138. @return {Promise}
  139. */
  140. ajax: function (method, url, options) {
  141. let self = this,
  142. ajaxSettings = {};
  143. Object.assign(ajaxSettings, this.ajaxSettings);
  144. if (typeof options === 'object' && !isNone(options)) {
  145. Object.assign(ajaxSettings, options);
  146. }
  147.  
  148. if (typeof method !== 'string' || isBlank(method)) {
  149. throw new Error(`ajax request method is invalid: ${method}`);
  150. }
  151.  
  152. if (typeof url !== 'string' || isBlank(url)) {
  153. throw new Error(`ajax request url is invalid: ${url}`);
  154. }
  155.  
  156. Object.assign(ajaxSettings, { type: method, url: url });
  157. if (
  158. ajaxSettings.contentType === 'application/json' &&
  159. ajaxSettings['data'] &&
  160. isArray(this.needSerializedMethod) &&
  161. this.needSerializedMethod.includes(method)
  162. ) {
  163. ajaxSettings['data'] = JSON.stringify(ajaxSettings['data']);
  164. }
  165. self.trigger('ajaxStart');
  166. return new Promise(function (resolve, reject) {
  167. // eslint-disable-next-line ember/no-jquery
  168. $.ajax(ajaxSettings)
  169. .done(function (data) {
  170. self.trigger('ajaxDone');
  171. try {
  172. resolve(self.RESTSerializer(data));
  173. self.trigger('ajaxSuccess');
  174. } catch (e) {
  175. self.trigger('RESTSerializerError', e);
  176. reject(e);
  177. }
  178. })
  179. .fail(function (jqXHR, responseText, errorThrown) {
  180. self.trigger('ajaxDone');
  181. console.log(jqXHR);
  182. console.log(ajaxSettings);
  183. let error = `${responseText} ${errorThrown}`;
  184. self.trigger('ajaxError', error, ajaxSettings, jqXHR);
  185. reject(new Error(error));
  186. });
  187. });
  188. },
  189. /**
  190. all ajax response data serializer
  191. @method RESTSerializer
  192. @param {Object} data response data
  193. @return serializer data
  194. */
  195. RESTSerializer: function (data) {
  196. console.log(
  197. 'subclass override RESTSerializer for response data serializer'
  198. );
  199. return data;
  200. },
  201. /**
  202. get method response data serializer
  203. @method getSerializer
  204. @param {Object} data response data
  205. @return serializer data
  206. */
  207. getSerializer: function (data) {
  208. console.log(
  209. 'subclass override getSerializer for get response data serializer'
  210. );
  211. return data;
  212. },
  213. /**
  214. post method response data serializer
  215. @method postSerializer
  216. @param {Object} data response data
  217. @return serializer data
  218. */
  219. postSerializer: function (data) {
  220. console.log(
  221. 'subclass override postSerializer for post response data serializer'
  222. );
  223. return data;
  224. },
  225. /**
  226. put method response data serializer
  227. @method putSerializer
  228. @param {Object} data response data
  229. @return serializer data
  230. */
  231. putSerializer: function (data) {
  232. console.log(
  233. 'subclass override putSerializer for put response data serializer'
  234. );
  235. return data;
  236. },
  237. /**
  238. delete method response data serializer
  239. @method deleteSerializer
  240. @param {Object} data response data
  241. @return serializer data
  242. */
  243. deleteSerializer: function (data) {
  244. console.log(
  245. 'subclass override deleteSerializer for delete response data serializer'
  246. );
  247. return data;
  248. },
  249. init: function () {
  250. this._super(...arguments);
  251. let self = this;
  252. const request = {
  253. parent: self,
  254. get: _get,
  255. post: _post,
  256. put: _put,
  257. delete: _delete,
  258. };
  259. this.set('needSerializedMethod', A(['post', 'put']));
  260. this.set('request', request);
  261. },
  262. });
  263.