From 76333fc672fc4b53719bac2832a27ea9c1be584b Mon Sep 17 00:00:00 2001 From: Matt Broadstone Date: Fri, 14 Feb 2020 17:50:43 -0500 Subject: [PATCH] refactor: use `maybePromise` instead of fake operations --- lib/cursor.js | 94 +++++++++++++++++++++++++++++++------- lib/operations/explain.js | 23 ---------- lib/operations/has_next.js | 40 ---------------- lib/operations/next.js | 32 ------------- lib/operations/to_array.js | 66 -------------------------- 5 files changed, 78 insertions(+), 177 deletions(-) delete mode 100644 lib/operations/explain.js delete mode 100644 lib/operations/has_next.js delete mode 100644 lib/operations/next.js delete mode 100644 lib/operations/to_array.js diff --git a/lib/cursor.js b/lib/cursor.js index bed709be354..618b0f544ba 100644 --- a/lib/cursor.js +++ b/lib/cursor.js @@ -9,16 +9,12 @@ const MongoError = require('./core').MongoError; const CoreCursor = require('./core/cursor').CoreCursor; const CursorState = require('./core/cursor').CursorState; const Map = require('./core').BSON.Map; +const maybePromise = require('./utils').maybePromise; +const executeOperation = require('./operations/execute_operation'); const each = require('./operations/cursor_ops').each; - const CountOperation = require('./operations/count'); -const ExplainOperation = require('./operations/explain'); -const HasNextOperation = require('./operations/has_next'); -const NextOperation = require('./operations/next'); -const ToArrayOperation = require('./operations/to_array'); - -const executeOperation = require('./operations/execute_operation'); +const nextObject = require('./operations/common_functions').nextObject; /** * @fileOverview The **Cursor** class is an internal class that embodies a cursor on MongoDB @@ -199,9 +195,25 @@ class Cursor extends CoreCursor { * @return {Promise} returns Promise if no callback passed */ hasNext(callback) { - const hasNextOperation = new HasNextOperation(this); + return maybePromise(callback, cb => { + const cursor = this; + if (cursor.s.currentDoc) { + return cb(null, true); + } + + if (cursor.isNotified()) { + return cb(null, false); + } - return executeOperation(this.topology, hasNextOperation, callback); + nextObject(cursor, (err, doc) => { + if (err) return cb(err); + if (cursor.s.state === Cursor.CLOSED || cursor.isDead()) return cb(null, false); + if (!doc) return cb(null, false); + + cursor.s.currentDoc = doc; + cb(null, true); + }); + }); } /** @@ -212,9 +224,19 @@ class Cursor extends CoreCursor { * @return {Promise} returns Promise if no callback passed */ next(callback) { - const nextOperation = new NextOperation(this); + return maybePromise(callback, cb => { + const cursor = this; + + // Return the currentDoc if someone called hasNext first + if (cursor.s.currentDoc) { + const doc = cursor.s.currentDoc; + cursor.s.currentDoc = null; + return cb(null, doc); + } - return executeOperation(this.topology, nextOperation, callback); + // Return the next object + nextObject(cursor, cb); + }); } /** @@ -784,9 +806,49 @@ class Cursor extends CoreCursor { }); } - const toArrayOperation = new ToArrayOperation(this); + return maybePromise(callback, cb => { + const cursor = this; + const items = []; - return executeOperation(this.topology, toArrayOperation, callback); + // Reset cursor + cursor.rewind(); + cursor.s.state = CursorState.INIT; + + // Fetch all the documents + const fetchDocs = () => { + cursor._next((err, doc) => { + if (err) { + return cursor._endSession + ? cursor._endSession(() => handleCallback(cb, err)) + : handleCallback(cb, err); + } + + if (doc == null) { + return cursor.close({ skipKillCursors: true }, () => handleCallback(cb, null, items)); + } + + // Add doc to items + items.push(doc); + + // Get all buffered objects + if (cursor.bufferedCount() > 0) { + let docs = cursor.readBufferedDocuments(cursor.bufferedCount()); + + // Transform the doc if transform method added + if (cursor.s.transforms && typeof cursor.s.transforms.doc === 'function') { + docs = docs.map(cursor.s.transforms.doc); + } + + Array.prototype.push.apply(items, docs); + } + + // Attempt a fetch + fetchDocs(); + }); + }; + + fetchDocs(); + }); } /** @@ -972,9 +1034,9 @@ class Cursor extends CoreCursor { delete this.cmd['readConcern']; } - const explainOperation = new ExplainOperation(this); - - return executeOperation(this.topology, explainOperation, callback); + return maybePromise(callback, cb => { + CoreCursor.prototype._next.apply(this, [cb]); + }); } /** diff --git a/lib/operations/explain.js b/lib/operations/explain.js deleted file mode 100644 index 44f3b483922..00000000000 --- a/lib/operations/explain.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -const Aspect = require('./operation').Aspect; -const CoreCursor = require('../core/cursor').CoreCursor; -const defineAspects = require('./operation').defineAspects; -const OperationBase = require('./operation').OperationBase; - -class ExplainOperation extends OperationBase { - constructor(cursor) { - super(); - - this.cursor = cursor; - } - - execute() { - const cursor = this.cursor; - return CoreCursor.prototype._next.apply(cursor, arguments); - } -} - -defineAspects(ExplainOperation, Aspect.SKIP_SESSION); - -module.exports = ExplainOperation; diff --git a/lib/operations/has_next.js b/lib/operations/has_next.js deleted file mode 100644 index b2e4b861d1c..00000000000 --- a/lib/operations/has_next.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -const Aspect = require('./operation').Aspect; -const defineAspects = require('./operation').defineAspects; -const loadCursor = require('../dynamic_loaders').loadCursor; -const OperationBase = require('./operation').OperationBase; -const nextObject = require('./common_functions').nextObject; - -class HasNextOperation extends OperationBase { - constructor(cursor) { - super(); - - this.cursor = cursor; - } - - execute(callback) { - const cursor = this.cursor; - let Cursor = loadCursor(); - - if (cursor.s.currentDoc) { - return callback(null, true); - } - - if (cursor.isNotified()) { - return callback(null, false); - } - - nextObject(cursor, (err, doc) => { - if (err) return callback(err, null); - if (cursor.s.state === Cursor.CLOSED || cursor.isDead()) return callback(null, false); - if (!doc) return callback(null, false); - cursor.s.currentDoc = doc; - callback(null, true); - }); - } -} - -defineAspects(HasNextOperation, Aspect.SKIP_SESSION); - -module.exports = HasNextOperation; diff --git a/lib/operations/next.js b/lib/operations/next.js deleted file mode 100644 index 72bc4eb9537..00000000000 --- a/lib/operations/next.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -const Aspect = require('./operation').Aspect; -const defineAspects = require('./operation').defineAspects; -const OperationBase = require('./operation').OperationBase; -const nextObject = require('./common_functions').nextObject; - -class NextOperation extends OperationBase { - constructor(cursor) { - super(); - - this.cursor = cursor; - } - - execute(callback) { - const cursor = this.cursor; - - // Return the currentDoc if someone called hasNext first - if (cursor.s.currentDoc) { - const doc = cursor.s.currentDoc; - cursor.s.currentDoc = null; - return callback(null, doc); - } - - // Return the next object - nextObject(cursor, callback); - } -} - -defineAspects(NextOperation, Aspect.SKIP_SESSION); - -module.exports = NextOperation; diff --git a/lib/operations/to_array.js b/lib/operations/to_array.js deleted file mode 100644 index db6d1a077c4..00000000000 --- a/lib/operations/to_array.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -const Aspect = require('./operation').Aspect; -const defineAspects = require('./operation').defineAspects; -const handleCallback = require('../utils').handleCallback; -const CursorState = require('../core/cursor').CursorState; -const OperationBase = require('./operation').OperationBase; -const push = Array.prototype.push; - -class ToArrayOperation extends OperationBase { - constructor(cursor) { - super(); - - this.cursor = cursor; - } - - execute(callback) { - const cursor = this.cursor; - const items = []; - - // Reset cursor - cursor.rewind(); - cursor.s.state = CursorState.INIT; - - // Fetch all the documents - const fetchDocs = () => { - cursor._next((err, doc) => { - if (err) { - return cursor._endSession - ? cursor._endSession(() => handleCallback(callback, err)) - : handleCallback(callback, err); - } - - if (doc == null) { - return cursor.close({ skipKillCursors: true }, () => - handleCallback(callback, null, items) - ); - } - - // Add doc to items - items.push(doc); - - // Get all buffered objects - if (cursor.bufferedCount() > 0) { - let docs = cursor.readBufferedDocuments(cursor.bufferedCount()); - - // Transform the doc if transform method added - if (cursor.s.transforms && typeof cursor.s.transforms.doc === 'function') { - docs = docs.map(cursor.s.transforms.doc); - } - - push.apply(items, docs); - } - - // Attempt a fetch - fetchDocs(); - }); - }; - - fetchDocs(); - } -} - -defineAspects(ToArrayOperation, Aspect.SKIP_SESSION); - -module.exports = ToArrayOperation;