@@ -25,6 +25,7 @@ var request = require('request').defaults({
25
25
maxSockets : Infinity
26
26
}
27
27
} ) ;
28
+ var through = require ( 'through2' ) ;
28
29
29
30
/**
30
31
* @type {module:datastore/entity }
@@ -92,11 +93,13 @@ function DatastoreRequest() {}
92
93
* transaction. Get operations require a valid key to retrieve the
93
94
* key-identified entity from Datastore.
94
95
*
96
+ * @throws {Error } If at least one Key object is not provided.
97
+ *
95
98
* @param {Key|Key[] } keys - Datastore key object(s).
96
99
* @param {function } callback - The callback function.
97
100
* @param {?error } callback.err - An error returned while making this request
98
101
* @param {module:datastore/entity|module:datastore/entity[] } callback.entity -
99
- * Will return either a single Entity or a list of Entities
102
+ * Will return either a single Entity or a list of Entities.
100
103
* @param {object } callback.apiResponse - The full API response.
101
104
*
102
105
* @example
@@ -105,57 +108,98 @@ function DatastoreRequest() {}
105
108
* // your use, whether that be a Dataset or Transaction object.
106
109
* //-
107
110
*
111
+ * //-
108
112
* // Get a single entity.
113
+ * //-
109
114
* var key = dataset.key(['Company', 123]);
115
+ *
110
116
* transaction.get(key, function(err, entity, apiResponse) {});
111
117
*
112
- * // Get multiple entities at once.
113
- * transaction.get([
118
+ * //-
119
+ * // Get multiple entities at once with a callback.
120
+ * //-
121
+ * var keys = [
114
122
* dataset.key(['Company', 123]),
115
123
* dataset.key(['Product', 'Computer'])
116
- * ], function(err, entities, apiResponse) {});
124
+ * ];
125
+ *
126
+ * transaction.get(keys, function(err, entities, apiResponse) {});
127
+ *
128
+ * //-
129
+ * // Or, get the entities as a readable object stream.
130
+ * //-
131
+ * transaction.get(keys)
132
+ * .on('error', function(err, apiResponse) {})
133
+ * .on('data', function(entity) {
134
+ * // entity is an entity object.
135
+ * })
136
+ * .on('end', function() {
137
+ * // All entities retrieved.
138
+ * });
117
139
*/
118
140
DatastoreRequest . prototype . get = function ( keys , callback ) {
119
- var that = this ;
141
+ var self = this ;
120
142
121
- var isMultipleRequest = Array . isArray ( keys ) ;
122
- keys = isMultipleRequest ? keys : [ keys ] ;
143
+ var isStreamMode = ! callback ;
144
+ var stream ;
123
145
124
- callback = callback || util . noop ;
146
+ if ( isStreamMode ) {
147
+ stream = through . obj ( ) ;
148
+ }
125
149
126
- var req = {
127
- key : keys . map ( entity . keyToKeyProto )
150
+ var isSingleLookup = ! util . is ( keys , 'array' ) ;
151
+ keys = util . arrayize ( keys ) . map ( entity . keyToKeyProto ) ;
152
+
153
+ if ( keys . length === 0 ) {
154
+ throw new Error ( 'At least one Key object is required.' ) ;
155
+ }
156
+
157
+ var request = {
158
+ key : keys
128
159
} ;
129
160
130
- this . makeReq_ ( 'lookup' , req , function ( err , resp ) {
161
+ var entities = [ ] ;
162
+ this . makeReq_ ( 'lookup' , request , onApiResponse ) ;
163
+
164
+ function onApiResponse ( err , resp ) {
131
165
if ( err ) {
132
- callback ( err , null , resp ) ;
166
+ if ( isStreamMode ) {
167
+ stream . emit ( 'error' , err , resp ) ;
168
+ stream . end ( ) ;
169
+ } else {
170
+ callback ( err , null , resp ) ;
171
+ }
133
172
return ;
134
173
}
135
174
136
- var found = entity . formatArray ( resp . found ) ;
137
-
138
- if ( isMultipleRequest && resp . deferred && resp . deferred . length ) {
139
- // There may be more results. Call `.get` again, and append the results.
140
- that . get (
141
- resp . deferred . map ( entity . keyFromKeyProto ) , function ( err , entities ) {
142
- if ( err ) {
143
- callback ( err , null , resp ) ;
144
- return ;
145
- }
146
-
147
- if ( resp ) {
148
- found = ( found || [ ] ) . concat ( entities ) ;
149
- }
175
+ var results = entity . formatArray ( resp . found ) ;
150
176
151
- callback ( null , found , resp ) ;
177
+ if ( isStreamMode ) {
178
+ results . forEach ( function ( entity ) {
179
+ stream . push ( entity ) ;
152
180
} ) ;
181
+ } else {
182
+ entities = entities . concat ( results ) ;
183
+ }
184
+
185
+ var nextKeys = ( resp . deferred || [ ] ) . map ( entity . keyFromKeyProto ) ;
153
186
187
+ if ( nextKeys . length > 0 ) {
188
+ self . get ( nextKeys , onApiResponse ) ;
154
189
return ;
155
190
}
156
191
157
- callback ( null , isMultipleRequest ? found : found [ 0 ] , resp ) ;
158
- } ) ;
192
+ if ( isStreamMode ) {
193
+ stream . push ( null ) ;
194
+ stream . end ( ) ;
195
+ } else {
196
+ callback ( null , isSingleLookup ? entities [ 0 ] : entities , resp ) ;
197
+ }
198
+ }
199
+
200
+ if ( isStreamMode ) {
201
+ return stream ;
202
+ }
159
203
} ;
160
204
161
205
/**
0 commit comments