custom_store.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /**
  2. * DevExtreme (data/custom_store.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var $ = require("../core/renderer");
  11. var dataUtils = require("./utils");
  12. var arrayUtils = require("./array_utils");
  13. var isFunction = require("../core/utils/type").isFunction;
  14. var config = require("../core/config");
  15. var errors = require("./errors").errors;
  16. var Store = require("./abstract_store");
  17. var arrayQuery = require("./array_query");
  18. var queryByOptions = require("./store_helper").queryByOptions;
  19. var deferredUtils = require("../core/utils/deferred");
  20. var Deferred = deferredUtils.Deferred;
  21. var when = deferredUtils.when;
  22. var fromPromise = deferredUtils.fromPromise;
  23. var TOTAL_COUNT = "totalCount";
  24. var LOAD = "load";
  25. var BY_KEY = "byKey";
  26. var INSERT = "insert";
  27. var UPDATE = "update";
  28. var REMOVE = "remove";
  29. function isPromise(obj) {
  30. return obj && isFunction(obj.then)
  31. }
  32. function trivialPromise(value) {
  33. return (new Deferred).resolve(value).promise()
  34. }
  35. function ensureRequiredFuncOption(name, obj) {
  36. if (!isFunction(obj)) {
  37. throw errors.Error("E4011", name)
  38. }
  39. }
  40. function throwInvalidUserFuncResult(name) {
  41. throw errors.Error("E4012", name)
  42. }
  43. function createUserFuncFailureHandler(pendingDeferred) {
  44. function errorMessageFromXhr(promiseArguments) {
  45. var xhr = promiseArguments[0];
  46. var textStatus = promiseArguments[1];
  47. if (!xhr || !xhr.getResponseHeader) {
  48. return null
  49. }
  50. return dataUtils.errorMessageFromXhr(xhr, textStatus)
  51. }
  52. return function(arg) {
  53. var error;
  54. if (arg instanceof Error) {
  55. error = arg
  56. } else {
  57. error = new Error(errorMessageFromXhr(arguments) || arg && String(arg) || "Unknown error")
  58. }
  59. if (error.message !== dataUtils.XHR_ERROR_UNLOAD) {
  60. pendingDeferred.reject(error)
  61. }
  62. }
  63. }
  64. function invokeUserLoad(store, options) {
  65. var userFunc = store._loadFunc;
  66. var userResult;
  67. ensureRequiredFuncOption(LOAD, userFunc);
  68. userResult = userFunc.apply(store, [options]);
  69. if (Array.isArray(userResult)) {
  70. userResult = trivialPromise(userResult)
  71. } else {
  72. if (null === userResult || void 0 === userResult) {
  73. userResult = trivialPromise([])
  74. } else {
  75. if (!isPromise(userResult)) {
  76. throwInvalidUserFuncResult(LOAD)
  77. }
  78. }
  79. }
  80. return fromPromise(userResult)
  81. }
  82. function invokeUserTotalCountFunc(store, options) {
  83. var userFunc = store._totalCountFunc;
  84. var userResult;
  85. if (!isFunction(userFunc)) {
  86. throw errors.Error("E4021")
  87. }
  88. userResult = userFunc.apply(store, [options]);
  89. if (!isPromise(userResult)) {
  90. userResult = Number(userResult);
  91. if (!isFinite(userResult)) {
  92. throwInvalidUserFuncResult(TOTAL_COUNT)
  93. }
  94. userResult = trivialPromise(userResult)
  95. }
  96. return fromPromise(userResult)
  97. }
  98. function invokeUserByKeyFunc(store, key, extraOptions) {
  99. var userFunc = store._byKeyFunc;
  100. var userResult;
  101. ensureRequiredFuncOption(BY_KEY, userFunc);
  102. userResult = userFunc.apply(store, [key, extraOptions]);
  103. if (!isPromise(userResult)) {
  104. userResult = trivialPromise(userResult)
  105. }
  106. return fromPromise(userResult)
  107. }
  108. function runRawLoad(pendingDeferred, store, userFuncOptions, continuation) {
  109. if (store.__rawData) {
  110. continuation(store.__rawData)
  111. } else {
  112. var loadPromise = store.__rawDataPromise || invokeUserLoad(store, userFuncOptions);
  113. if (store._cacheRawData) {
  114. store.__rawDataPromise = loadPromise
  115. }
  116. loadPromise.always(function() {
  117. delete store.__rawDataPromise
  118. }).done(function(rawData) {
  119. if (store._cacheRawData) {
  120. store.__rawData = rawData
  121. }
  122. continuation(rawData)
  123. }).fail(createUserFuncFailureHandler(pendingDeferred))
  124. }
  125. }
  126. function runRawLoadWithQuery(pendingDeferred, store, options, countOnly) {
  127. options = options || {};
  128. var userFuncOptions = {};
  129. if ("userData" in options) {
  130. userFuncOptions.userData = options.userData
  131. }
  132. runRawLoad(pendingDeferred, store, userFuncOptions, function(rawData) {
  133. var rawDataQuery = arrayQuery(rawData, {
  134. errorHandler: store._errorHandler
  135. });
  136. var itemsQuery;
  137. var totalCountQuery;
  138. var waitList = [];
  139. var items;
  140. var totalCount;
  141. if (!countOnly) {
  142. itemsQuery = queryByOptions(rawDataQuery, options);
  143. if (itemsQuery === rawDataQuery) {
  144. items = rawData.slice(0)
  145. } else {
  146. waitList.push(itemsQuery.enumerate().done(function(asyncResult) {
  147. items = asyncResult
  148. }))
  149. }
  150. }
  151. if (options.requireTotalCount || countOnly) {
  152. totalCountQuery = queryByOptions(rawDataQuery, options, true);
  153. if (totalCountQuery === rawDataQuery) {
  154. totalCount = rawData.length
  155. } else {
  156. waitList.push(totalCountQuery.count().done(function(asyncResult) {
  157. totalCount = asyncResult
  158. }))
  159. }
  160. }
  161. when.apply($, waitList).done(function() {
  162. if (countOnly) {
  163. pendingDeferred.resolve(totalCount)
  164. } else {
  165. if (options.requireTotalCount) {
  166. pendingDeferred.resolve(items, {
  167. totalCount: totalCount
  168. })
  169. } else {
  170. pendingDeferred.resolve(items)
  171. }
  172. }
  173. }).fail(function(x) {
  174. pendingDeferred.reject(x)
  175. })
  176. })
  177. }
  178. function runRawLoadWithKey(pendingDeferred, store, key) {
  179. runRawLoad(pendingDeferred, store, {}, function(rawData) {
  180. var keyExpr = store.key();
  181. var item;
  182. for (var i = 0, len = rawData.length; i < len; i++) {
  183. item = rawData[i];
  184. if (dataUtils.keysEqual(keyExpr, store.keyOf(rawData[i]), key)) {
  185. pendingDeferred.resolve(item);
  186. return
  187. }
  188. }
  189. pendingDeferred.reject(errors.Error("E4009"))
  190. })
  191. }
  192. var CustomStore = Store.inherit({
  193. ctor: function(options) {
  194. options = options || {};
  195. this.callBase(options);
  196. this._useDefaultSearch = !!options.useDefaultSearch || "raw" === options.loadMode;
  197. this._loadMode = options.loadMode;
  198. this._cacheRawData = false !== options.cacheRawData;
  199. this._loadFunc = options[LOAD];
  200. this._totalCountFunc = options[TOTAL_COUNT];
  201. this._byKeyFunc = options[BY_KEY];
  202. this._insertFunc = options[INSERT];
  203. this._updateFunc = options[UPDATE];
  204. this._removeFunc = options[REMOVE]
  205. },
  206. createQuery: function() {
  207. throw errors.Error("E4010")
  208. },
  209. clearRawDataCache: function() {
  210. delete this.__rawData
  211. },
  212. _totalCountImpl: function(options) {
  213. var d = new Deferred;
  214. if ("raw" === this._loadMode && !this._totalCountFunc) {
  215. runRawLoadWithQuery(d, this, options, true)
  216. } else {
  217. invokeUserTotalCountFunc(this, options).done(function(count) {
  218. d.resolve(Number(count))
  219. }).fail(createUserFuncFailureHandler(d));
  220. d = this._addFailHandlers(d)
  221. }
  222. return d.promise()
  223. },
  224. _pushImpl: function(changes) {
  225. if (this.__rawData) {
  226. arrayUtils.applyBatch(this, this.__rawData, changes)
  227. }
  228. },
  229. _loadImpl: function(options) {
  230. var d = new Deferred;
  231. if ("raw" === this._loadMode) {
  232. runRawLoadWithQuery(d, this, options, false)
  233. } else {
  234. invokeUserLoad(this, options).done(function(data, extra) {
  235. d.resolve(data, extra)
  236. }).fail(createUserFuncFailureHandler(d));
  237. d = this._addFailHandlers(d)
  238. }
  239. return d.promise()
  240. },
  241. _byKeyImpl: function(key, extraOptions) {
  242. var d = new Deferred;
  243. if (this._byKeyViaLoad()) {
  244. this._requireKey();
  245. runRawLoadWithKey(d, this, key)
  246. } else {
  247. invokeUserByKeyFunc(this, key, extraOptions).done(function(obj) {
  248. d.resolve(obj)
  249. }).fail(createUserFuncFailureHandler(d))
  250. }
  251. return d.promise()
  252. },
  253. _byKeyViaLoad: function() {
  254. return "raw" === this._loadMode && !this._byKeyFunc
  255. },
  256. _insertImpl: function(values) {
  257. var that = this;
  258. var userFunc = that._insertFunc;
  259. var userResult;
  260. var d = new Deferred;
  261. ensureRequiredFuncOption(INSERT, userFunc);
  262. userResult = userFunc.apply(that, [values]);
  263. if (!isPromise(userResult)) {
  264. userResult = trivialPromise(userResult)
  265. }
  266. fromPromise(userResult).done(function(serverResponse) {
  267. if (config().useLegacyStoreResult) {
  268. d.resolve(values, serverResponse)
  269. } else {
  270. d.resolve(serverResponse || values, that.keyOf(serverResponse))
  271. }
  272. }).fail(createUserFuncFailureHandler(d));
  273. return d.promise()
  274. },
  275. _updateImpl: function(key, values) {
  276. var userFunc = this._updateFunc;
  277. var userResult;
  278. var d = new Deferred;
  279. ensureRequiredFuncOption(UPDATE, userFunc);
  280. userResult = userFunc.apply(this, [key, values]);
  281. if (!isPromise(userResult)) {
  282. userResult = trivialPromise(userResult)
  283. }
  284. fromPromise(userResult).done(function(serverResponse) {
  285. if (config().useLegacyStoreResult) {
  286. d.resolve(key, values)
  287. } else {
  288. d.resolve(serverResponse || values, key)
  289. }
  290. }).fail(createUserFuncFailureHandler(d));
  291. return d.promise()
  292. },
  293. _removeImpl: function(key) {
  294. var userFunc = this._removeFunc;
  295. var userResult;
  296. var d = new Deferred;
  297. ensureRequiredFuncOption(REMOVE, userFunc);
  298. userResult = userFunc.apply(this, [key]);
  299. if (!isPromise(userResult)) {
  300. userResult = trivialPromise()
  301. }
  302. fromPromise(userResult).done(function() {
  303. d.resolve(key)
  304. }).fail(createUserFuncFailureHandler(d));
  305. return d.promise()
  306. }
  307. });
  308. module.exports = CustomStore;
  309. module.exports.default = module.exports;