From cf08d94b30412d8d4e96378bc2c240fdc0667881 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Thu, 3 Oct 2019 19:38:25 +0300 Subject: [PATCH] Fix floating promise in constructor (closes #656) (#680) --- README.md | 3 ++- lib/levelup.js | 5 ++++- test/init-test.js | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d744b4cc..29ad7942 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ The main entry point for creating a new `levelup` instance. - `db` must be an [`abstract-leveldown`](https://github.com/Level/abstract-leveldown) compliant store. - `options` is passed on to the underlying store when opened and is specific to the type of store being used -Calling `levelup(db)` will also open the underlying store. This is an asynchronous operation which will trigger your callback if you provide one. The callback should take the form `function (err, db) {}` where `db` is the `levelup` instance. If you don't provide a callback, any read & write operations are simply queued internally until the store is fully opened. +Calling `levelup(db)` will also open the underlying store. This is an asynchronous operation which will trigger your callback if you provide one. The callback should take the form `function (err, db) {}` where `db` is the `levelup` instance. If you don't provide a callback, any read & write operations are simply queued internally until the store is fully opened, unless it fails to open, in which case an `error` event will be emitted. This leads to two alternative ways of managing a `levelup` instance: @@ -487,6 +487,7 @@ const main = async () => { | `ready` | Alias of `open` | - | | `closing` | Store is closing | - | | `closed` | Store has closed. | - | +| `error` | An error occurred | `error` (Error) | For example you can do: diff --git a/lib/levelup.js b/lib/levelup.js index 1fd876b7..60e2ef74 100644 --- a/lib/levelup.js +++ b/lib/levelup.js @@ -31,6 +31,7 @@ function LevelUP (db, options, callback) { } var error + var self = this EventEmitter.call(this) this.setMaxListeners(Infinity) @@ -55,7 +56,9 @@ function LevelUP (db, options, callback) { this.options = getOptions(options) this._db = db this.db = new DeferredLevelDOWN(db) - this.open(callback) + this.open(callback || function (err) { + if (err) self.emit('error', err) + }) // Create manifest based on deferred-leveldown's this.supports = supports(this.db.supports, { diff --git a/test/init-test.js b/test/init-test.js index e053b7a3..1739b910 100644 --- a/test/init-test.js +++ b/test/init-test.js @@ -39,6 +39,40 @@ module.exports = function (test, testCommon) { }) }) + test('Init & open(): error with callback', function (t) { + t.plan(1) + + var mem = memdown() + mem._open = function (opts, cb) { + process.nextTick(cb, new Error('from underlying store')) + } + + levelup(mem, function (err) { + t.is(err.message, 'from underlying store') + }).on('open', function () { + t.fail('should not finish opening') + }).on('error', function () { + t.fail('should not emit error') + }) + }) + + test('Init & open(): error without callback', function (t) { + t.plan(1) + + var mem = memdown() + mem._open = function (opts, cb) { + process.nextTick(cb, new Error('from underlying store')) + } + + levelup(mem) + .on('open', function () { + t.fail('should not finish opening') + }) + .on('error', function (err) { + t.is(err.message, 'from underlying store') + }) + }) + test('Init & open(): validate abstract-leveldown', function (t) { t.plan(1)