Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix floating promise in constructor #680

Merged
merged 1 commit into from Oct 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -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:

Expand Down Expand Up @@ -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:

Expand Down
5 changes: 4 additions & 1 deletion lib/levelup.js
Expand Up @@ -31,6 +31,7 @@ function LevelUP (db, options, callback) {
}

var error
var self = this

EventEmitter.call(this)
this.setMaxListeners(Infinity)
Expand All @@ -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, {
Expand Down
34 changes: 34 additions & 0 deletions test/init-test.js
Expand Up @@ -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)

Expand Down