UNPKG

8.98 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
5Object.defineProperty(exports, "__esModule", {
6 value: true
7});
8exports["default"] = void 0;
9
10var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
11
12var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
13
14var _resultSummary = _interopRequireDefault(require("./result-summary"));
15
16var _connectionHolder = require("./internal/connection-holder");
17
18var _streamObservers = require("./internal/stream-observers");
19
20/**
21 * Copyright (c) 2002-2019 "Neo4j,"
22 * Neo4j Sweden AB [http://neo4j.com]
23 *
24 * This file is part of Neo4j.
25 *
26 * Licensed under the Apache License, Version 2.0 (the "License");
27 * you may not use this file except in compliance with the License.
28 * You may obtain a copy of the License at
29 *
30 * http://www.apache.org/licenses/LICENSE-2.0
31 *
32 * Unless required by applicable law or agreed to in writing, software
33 * distributed under the License is distributed on an "AS IS" BASIS,
34 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35 * See the License for the specific language governing permissions and
36 * limitations under the License.
37 */
38var DEFAULT_ON_ERROR = function DEFAULT_ON_ERROR(error) {
39 console.log('Uncaught error when processing result: ' + error);
40};
41
42var DEFAULT_ON_COMPLETED = function DEFAULT_ON_COMPLETED(summary) {};
43
44var DEFAULT_METADATA_SUPPLIER = function DEFAULT_METADATA_SUPPLIER(metadata) {};
45/**
46 * A stream of {@link Record} representing the result of a query.
47 * Can be consumed eagerly as {@link Promise} resolved with array of records and {@link ResultSummary}
48 * summary, or rejected with error that contains {@link string} code and {@link string} message.
49 * Alternatively can be consumed lazily using {@link Result#subscribe} function.
50 * @access public
51 */
52
53
54var Result =
55/*#__PURE__*/
56function () {
57 /**
58 * Inject the observer to be used.
59 * @constructor
60 * @access private
61 * @param {Promise<ResultStreamObserver>} streamObserverPromise
62 * @param {mixed} query - Cypher query to execute
63 * @param {Object} parameters - Map with parameters to use in query
64 * @param {ConnectionHolder} connectionHolder - to be notified when result is either fully consumed or error happened.
65 */
66 function Result(streamObserverPromise, query, parameters, connectionHolder) {
67 (0, _classCallCheck2["default"])(this, Result);
68 this._stack = captureStacktrace();
69 this._streamObserverPromise = streamObserverPromise;
70 this._p = null;
71 this._query = query;
72 this._parameters = parameters || {};
73 this._connectionHolder = connectionHolder || _connectionHolder.EMPTY_CONNECTION_HOLDER;
74 }
75 /**
76 * Returns a promise for the field keys.
77 *
78 * *Should not be combined with {@link Result#subscribe} function.*
79 *
80 * @public
81 * @returns {Promise<string[]>} - Field keys, in the order they will appear in records.
82 }
83 */
84
85
86 (0, _createClass2["default"])(Result, [{
87 key: "keys",
88 value: function keys() {
89 var _this = this;
90
91 return new Promise(function (resolve, reject) {
92 _this._streamObserverPromise.then(function (observer) {
93 return observer.subscribe({
94 onKeys: function onKeys(keys) {
95 return resolve(keys);
96 },
97 onError: function onError(err) {
98 return reject(err);
99 }
100 });
101 });
102 });
103 }
104 /**
105 * Returns a promise for the result summary.
106 *
107 * *Should not be combined with {@link Result#subscribe} function.*
108 *
109 * @public
110 * @returns {Promise<ResultSummary>} - Result summary.
111 *
112 */
113
114 }, {
115 key: "summary",
116 value: function summary() {
117 var _this2 = this;
118
119 return new Promise(function (resolve, reject) {
120 _this2._streamObserverPromise.then(function (o) {
121 o.cancel();
122 o.subscribe({
123 onCompleted: function onCompleted(metadata) {
124 return resolve(metadata);
125 },
126 onError: function onError(err) {
127 return reject(err);
128 }
129 });
130 });
131 });
132 }
133 /**
134 * Create and return new Promise
135 *
136 * @private
137 * @return {Promise} new Promise.
138 */
139
140 }, {
141 key: "_getOrCreatePromise",
142 value: function _getOrCreatePromise() {
143 var _this3 = this;
144
145 if (!this._p) {
146 this._p = new Promise(function (resolve, reject) {
147 var records = [];
148 var observer = {
149 onNext: function onNext(record) {
150 records.push(record);
151 },
152 onCompleted: function onCompleted(summary) {
153 resolve({
154 records: records,
155 summary: summary
156 });
157 },
158 onError: function onError(error) {
159 reject(error);
160 }
161 };
162
163 _this3.subscribe(observer);
164 });
165 }
166
167 return this._p;
168 }
169 /**
170 * Waits for all results and calls the passed in function with the results.
171 *
172 * *Should not be combined with {@link Result#subscribe} function.*
173 *
174 * @param {function(result: {records:Array<Record>, summary: ResultSummary})} onFulfilled - function to be called
175 * when finished.
176 * @param {function(error: {message:string, code:string})} onRejected - function to be called upon errors.
177 * @return {Promise} promise.
178 */
179
180 }, {
181 key: "then",
182 value: function then(onFulfilled, onRejected) {
183 return this._getOrCreatePromise().then(onFulfilled, onRejected);
184 }
185 /**
186 * Catch errors when using promises.
187 *
188 * *Should not be combined with {@link Result#subscribe} function.*
189 *
190 * @param {function(error: Neo4jError)} onRejected - Function to be called upon errors.
191 * @return {Promise} promise.
192 */
193
194 }, {
195 key: "catch",
196 value: function _catch(onRejected) {
197 return this._getOrCreatePromise()["catch"](onRejected);
198 }
199 /**
200 * Stream records to observer as they come in, this is a more efficient method
201 * of handling the results, and allows you to handle arbitrarily large results.
202 *
203 * @param {Object} observer - Observer object
204 * @param {function(keys: string[])} observer.onKeys - handle stream head, the field keys.
205 * @param {function(record: Record)} observer.onNext - handle records, one by one.
206 * @param {function(summary: ResultSummary)} observer.onCompleted - handle stream tail, the result summary.
207 * @param {function(error: {message:string, code:string})} observer.onError - handle errors.
208 * @return
209 */
210
211 }, {
212 key: "subscribe",
213 value: function subscribe(observer) {
214 var _this4 = this;
215
216 var onCompletedOriginal = observer.onCompleted || DEFAULT_ON_COMPLETED;
217
218 var onCompletedWrapper = function onCompletedWrapper(metadata) {
219 // notify connection holder that the used connection is not needed any more because result has
220 // been fully consumed; call the original onCompleted callback after that
221 _this4._connectionHolder.releaseConnection().then(function () {
222 onCompletedOriginal.call(observer, new _resultSummary["default"](_this4._query, _this4._parameters, metadata));
223 });
224 };
225
226 observer.onCompleted = onCompletedWrapper;
227 var onErrorOriginal = observer.onError || DEFAULT_ON_ERROR;
228
229 var onErrorWrapper = function onErrorWrapper(error) {
230 // notify connection holder that the used connection is not needed any more because error happened
231 // and result can't bee consumed any further; call the original onError callback after that
232 _this4._connectionHolder.releaseConnection().then(function () {
233 replaceStacktrace(error, _this4._stack);
234 onErrorOriginal.call(observer, error);
235 });
236 };
237
238 observer.onError = onErrorWrapper;
239
240 this._streamObserverPromise.then(function (o) {
241 return o.subscribe(observer);
242 });
243 }
244 /**
245 * Signals the stream observer that the future records should be discarded on the server.
246 *
247 * @protected
248 * @since 4.0.0
249 */
250
251 }, {
252 key: "_cancel",
253 value: function _cancel() {
254 this._streamObserverPromise.then(function (o) {
255 return o.cancel();
256 });
257 }
258 }]);
259 return Result;
260}();
261
262function captureStacktrace() {
263 var error = new Error('');
264
265 if (error.stack) {
266 return error.stack.replace(/^Error(\n\r)*/, ''); // we don't need the 'Error\n' part, if only it exists
267 }
268
269 return null;
270}
271
272function replaceStacktrace(error, newStack) {
273 if (newStack) {
274 // Error.prototype.toString() concatenates error.name and error.message nicely
275 // then we add the rest of the stack trace
276 error.stack = error.toString() + '\n' + newStack;
277 }
278}
279
280var _default = Result;
281exports["default"] = _default;
\No newline at end of file