-
Notifications
You must be signed in to change notification settings - Fork 166
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
Promise support for Nano - Issue 98 #102
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great work. Just some smaller changes and then I think this is good to go.
|
||
// Do not wait for the index to finish building to return results. | ||
stale?: boolean | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow nice work. The definitions are nice and clear now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
lib/nano.js
Outdated
var responseHandler = function(req, opts, resolve, reject, callback) { | ||
|
||
return function(e, h, b) { | ||
var parsed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we only supporting more modern nodejs versions. You can use let
for var
. But ideally use a const
. So when you define an object use const
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure how far to go with the modernisation of the code. If we're going to use const
here, then I'll take a look at doing const
/let
everywhere else too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well maybe do that in a separate PR.
Lets get this landed. Then do a modernisation and then do a release for 7.0.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
lib/nano.js
Outdated
|
||
return function(e, h, b) { | ||
var parsed; | ||
var rh = h && h.headers || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be simplified to:
const responseHeader = Object.assign({
uri: req.uri,
statusCode: h.statusCode
}, h.headers);
I'm not a huge fan of such short variable names. Its difficult to figure out what it is. I would before something that explains what this is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 This e/h/b business is historic. I've refactored this function to aid readability.
lib/nano.js
Outdated
@@ -68,6 +67,89 @@ module.exports = exports = nano = function dbScope(cfg) { | |||
} | |||
return str; | |||
} | |||
var responseHandler = function(req, opts, resolve, reject, callback) { | |||
|
|||
return function(e, h, b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do a fiew checks lower to check if h exists. You can do something like this instead:
return function (e, h = {}, b) {
That way h
will default to an empty header. Also could you rename it to header because I think that is what it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 h
is actually the response!! h
is from the original code. I'm refactoring with sensible names!
lib/nano.js
Outdated
rh.uri = req.uri; | ||
if (e) { | ||
log({err: 'socket', body: b, headers: rh}); | ||
var ret_e = errs.merge(e, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we using camel case so this should be const retE
or `returnError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
lib/nano.js
Outdated
}, function(err, body, headers) { | ||
if (err) { | ||
if (callback) { | ||
callback(err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would there be a case you want the body and headers for an error as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point 👍
return view(ddoc, viewName, {type: 'view', stream: true}, qs, callback); | ||
} | ||
|
||
|
||
// geocouch | ||
function viewSpatial(ddoc, viewName, qs, callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might have ton consider dropping support for Geocouch. It doesn't work with CouchDb 2.x
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll create an issue to track this.#103
lib/nano.js
Outdated
@@ -738,6 +825,25 @@ module.exports = exports = nano = function dbScope(cfg) { | |||
}, callback); | |||
} | |||
|
|||
function insertAttAsStream(docName, attName, att, contentType, qs, callback) { | |||
if (typeof qs === 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have this check everywhere. You could consider a function that does this everywhere for us.
const {qs, callback} = getCallback(qs0, callback0);
function getCallback (opts, callback) {
if (typeof opts === 'function') {
callback = opts;
qs = {};
}
return {
qs,
callback
};
}
It might make things a little neater. I know we do something similar in PouchDB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 done
migration_6_to_7.md
Outdated
|
||
```js | ||
// Nano 7 | ||
var db = nano.db.use('mydb') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets promote good practice and use const
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
migration_6_to_7.md
Outdated
```js | ||
// Nano 7 | ||
var db = nano.db.use('mydb') | ||
var x = db.get('mydoc') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could maybe make this const x = await db.get('mydoc');
To show its a promise and we could use async/await
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -3,11 +3,12 @@ | |||
"node": true, | |||
"strict": true, | |||
"smarttabs": true, | |||
"maxlen": 80, | |||
"maxlen": 100, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naughty!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nicely done @glynnbird! I gave it a very shot spin in a local project and it seems to work just fine.
```js | ||
// Nano 7 | ||
const db = nano.db.use('mydb') | ||
const x = await db.get('mydoc') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x is a what now? (just so the examples have parity)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
migration_6_to_7.md
Outdated
}) | ||
``` | ||
|
||
The Promise style of code lets you code sequences of asynchronou calls at the same level of indentation (the callback style forces you to indent further to the right with each call!): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/asynchrnonou/asynchrnonous/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
README.md
Outdated
}) | ||
``` | ||
|
||
or in the `async/await` style: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nickpick, but should we make this the first example and show raw promises second? The code is just so much nicer :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@glynnbird how does this relate to #88? |
@janl The idea of #88 was to make it so that Promises could be switched on with a config flag. A neat idea, but it plays havoc when you're using it with TypeScript which likes functions to return a fixed type, so instead I wrote-up issue #98 to make Promises the default - to mirror the expectations of the modern JS/TS user. That way the return values would always be Promises, which keeps TS happy and added some extra functions which return streams to the streamy stuff. So, in short, #88 was the inspiration, but it slightly different approach won the day. |
@glynnbird thanks for the context! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome. Thanks @glynnbird huge +1
|
||
return function(err, response = { statusCode: 500 }, body = '') { | ||
let parsed; | ||
const responseHeaders = Object.assign({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks this is much clearer to read.
Overview
Aimed at a v7.x release of Nano, this PR makes Nano return a Promise instead of a Request object as its return value. See #98. This brings Nano into the modern world without breaking code that uses the callback style. It only breaks code that relied on the events emitted from the Request object or that piped the stream to another stream.
Work done in this PR:
migration_6_to_7
guideTesting recommendations
The tests have been updated to reflect the change. Instantiate a Nano instance and most operations will return a Promise:
GitHub issue number
#98
Related Pull Requests
#88
Checklist