-
Notifications
You must be signed in to change notification settings - Fork 4
/
RequestMemory.js
119 lines (101 loc) · 3.55 KB
/
RequestMemory.js
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
define([
'dojo/_base/declare',
'dojo/_base/lang',
'dojo/_base/array',
'dojo/when',
'dojo/request',
'dojo/store/Memory',
'dojo/store/util/QueryResults'
], function (declare, lang, arrayUtil, when, request, Memory, QueryResults) {
var Request = declare(Memory, {
// summary:
// Implementation of an in-memory store primed by data from an
// async request.
// url: String
// URL to request data from.
url: '',
// requestOptions: Object?
// Any options to pass to the request call, e.g. method, query, data...
requestOptions: null,
// alwaysPromise: Boolean
// If true (the default), get, add, put, remove, and query will always
// return promises as long as a URL has been set (not data). If false,
// any calls made after the response has been received will execute
// synchronously without routing through the promise from the request,
// which can yield better performance.
alwaysPromise: true,
constructor: function () {
var originalMethods = {};
if (this.url) {
this.setUrl(this.url);
}
// Wrap most of the instance methods here, in a loop, since they can all
// be wrapped the same. The query method is extended separately.
arrayUtil.forEach([ 'get', 'add', 'put', 'remove' ], function (method) {
originalMethods[method] = this[method];
this[method] = function () {
var args = arguments;
var self = this;
return when(this._promise, function () {
return originalMethods[method].apply(self, args);
});
};
}, this);
},
query: function (query, options) {
var self = this;
var ret = new QueryResults(when(this._promise, function () {
// This is slightly repetitive of dojo/store/Memory; we can't simply
// call inherited (would end up wrapping early with QueryResults).
return self.queryEngine(query, options)(self.data);
}));
ret.total = when(ret, function (results) {
// When the queryEngine call itself comes back, it will not have
// a total property unless it puts one there itself from processing
// a paging request. Fall back to length if it's missing (unpaged).
return 'total' in results ? results.total : results.length;
});
return ret;
},
setUrl: function (url) {
// summary:
// Sets the given URL as the source for this store, and indexes it
// url: String
// Specifies the URL to retrieve data from.
var self = this;
var promise = this._promise;
var options = lang.mixin({ handleAs: 'json' }, this.requestOptions);
if (promise && !promise.isFulfilled()) {
// Cancel in-flight request since a new URL has been provided.
promise.cancel();
}
// Store promise before chained handler to avoid confusion when
// setData checks fulfillment.
promise = this._promise = request(url, options);
promise.then(function (response) {
self.setData(response, self.alwaysPromise);
});
return promise;
},
setData: function (data, _keepPromise) {
// summary:
// Sets the given data as the source for this store, and indexes it.
// data: Array
// An array of objects to use as the source of data.
// _keepPromise: Boolean?
// Used internally by setUrl. There's no reason to specify this manually.
var promise = this._promise;
if (promise && !promise.isFulfilled()) {
// Cancel in-flight request since new data has been provided.
promise.cancel();
}
if (!_keepPromise) {
// Delete _promise (when setData is called directly, or
// alwaysPromise is false).
delete this._promise;
}
this.inherited(arguments);
}
});
return Request;
});