@google-cloud/datastoreUsing a callback approach with 1 key
get(key, (err, entity) => {} will output an object
whereas using a promise approach with 1 key
get(key).then(entity => {}) will output a 1 sized array containing the object
This is true for all of our methods, and that's why we do it-- for the consistency. Most of our methods return multiple arguments. datastore.get() is a rare exception. It's understandably confusing that we're using an array where only one value is expected, but we have to do it so users don't always have to confirm with our docs which methods resolve a promise with an array and which ones don't. Sorry for the confusion.
@stephenplusplus Hi there! A bit of feedback: this is confusing and hard to find an answer for. You should improve docs there.
Moreover, I don't think your answer addresses the question at all. Why doesn't the callback API return an array too then? That would consistent (although weird).
We have two ways of using every method, and I think if we dual-documented every method, we'd end up confusing everybody. In our documentation, each method has an examples section. If it can be run as a promise, it will show the response arguments to the then handler. That's where we show that an array is returned.
Why doesn't the callback API return an array too then?
We're trying to be consistent for each user. A promise user should expect us to be consistent with how we return responses in promise mode, and a callback user should expect us to be consistent with how we return responses in callback mode. We can't be consistent between callback and promise because of the promise spec, which refuses multiple arguments to a promise's resolution. In other words, we can't do this:
method().then(function(items, apiResponse) {})
We have to do put them into a single structure of either an array or object
method().then(function(resp) { resp[0] === items && resp[1] === apiResponse })
You should improve docs there.
I want this, too. How?
An introductory paragraph explaining the thing you just explained :) most libraries I've used in node return array for multiple results and objects for single results.
So I jumped to this conclusion and was confused
@stephenplusplus this brings up a good point - if we're deprecating the meta packages, perhaps we'll need to include instructions for things that would have typically belonged inside of the meta package overview everywhere else (e.g. interceptors, promises, config object, etc.)
Good thinking, maybe it should be part of the Overview template.
I see progress and I see no need for further commenting on my part.
Thank you very much and congrats on thorough feedback process.
(Coming from #1768). I have developed a few apps on App Engine for two years but not on Node. In my current project, I am using the Node datastore library for the first time as I am integrating it with Cloud Functions beta.
As a new user to the library, I have to check the docs and tutorials on how to use different methods. I didn't realize that there was consistency for "promise users" and "callback users", and I didn't realize that promise result arguments were designed to be consistent across various APIs until I read this thread.
To put it in another way, as a new user, the point on consistency for promise arguments across different APIs was not that important for me. I spent some time debugging why my batch get only had one element when I iterated over the outer array. Looking back, the docs did show an example that showed the need to access the first element of the array first.
That being said, experienced users may find the consistency to be highly beneficial. Establishing consistency is valuable to library developers as well. Just my two cents. Thanks!
I encountered this too and was confused until I read through this issue. Second the idea of adding some clarity in the documentation.
With regards @stephenplusplus comment about 'single structure of either an array or an object', why not then an object rather than array?
Instead of:
file.getMetadata().then(function(data) {
var metadata = data[0];
var apiResponse = data[1];
});
I could then:
file.getMetadata().then(function(data) {
var metadata = data.metadata;
var apiResponse = data.apiResponse;
});
@DazWilkin Ultimately we decided to go with arrays over objects to benefit users who use promise libraries that have a spread method.
@callmehiphop, is there anything actionable on this issue?
@sduskis I'm going to say no, our documentation format has completely changed since the time this issue was raised and the new(er) format clearly documents that promises are returned. I'm going to close this unless @stephenplusplus thinks we shouldn't