-
Notifications
You must be signed in to change notification settings - Fork 452
Async APIs should be returning Promises #88
Comments
👍 for Promises. |
I agree that a promise based API would be neat. When that have been said; I agree there are a lot of room for improvements of the cognito-identity JS library before it gets finalized and merged into the AWS-SDK-JS code base. |
@ribomation I take it your issue is with the mismatch in style, not implementation issues? I don't think this library is intended to be merged into the AWS SDK? Amazon provide plenty of support SDKs that sit on top of the raw SDK, but those may be temporary until merged too, for all I know. Ideally, of course, the same change would be made to the base SDK, then there's no problem :) |
In fact, AWS SDK 2.3 added Promises supprt! (sort-of) https://aws.amazon.com/releasenotes/SDK/JavaScript/8589740860839559 |
I will bring this up with the team so that we integrate it in our future roadmap. |
@itrestian So, what is the future roadmap?
I guess many developers, me included, is wondering about the status of this project; if and when we can start putting it into production code. |
The library was updated last week the General Availability launch of the feature. We will keep updating the library with more features down the road. Community contributions are also welcome and this should be fit for production use. It will stay as opt in library for now. Currently, we do not have any plans to merge this with AWS SDK. |
Would you guys be interested in a PR for this? The main issue is the The first can be handled by piggy-backing on With example usage picked to show off options: this.client.makeUnauthenticatedRequest('foo', { ... }, (err, fooRes) => {
if (err) {
return callback(err, null); // or return callback.onFailure(err);
}
this.client.makeUnauthenticatedRequest('bar', { ..., useFoo(fooRes) }, (err, barRes) => {
if (err) {
return callback(err, null); // or return callback.onFailure(err);
}
this.client.makeUnauthenticatedRequest('baz', { ..., useFooAndBar(fooRes, barRes) }, (err, bazRes) => {
callback(null, useBazRes(bazRes)); // or return callback.onSuccess();
});
}); Using just return handleCallback(callback, this.client.makeUnauthenticatedRequest('foo', { ... }).promise()
.then(fooRes =>
this.client.makeUnauthenticatedRequest('bar', { ..., useFoo(fooRes) }).promise()
.then(barRes =>
this.client.makeUnauthenticatedRequest('baz', { ..., useFooAndBar(fooRes, barRes) }).promise()
)
)
.then(bazRes => useBaz(bazRes)); Where function handleCallback(callback, promise) {
if (callback) {
if (typeof callback === 'function') {
return promise.then(
res => { callback(null, res); },
err => { callback(err, null); }
);
}
if (typeof callback === 'object' && callback.onSuccess && callback.onFailure) {
return promise.then(
res => { callback.onSuccess(res); },
err => { callback.onFailure(err); }
);
}
throw new Error('Bad callback');
}
return promise;
} Note that also unifies callbacks so users don't need to care which each method takes. The main problem would be supporting things like Probably easiest to have it simply reject with a well defined reason: user.authenticateUser(..., {
onSuccess() { showLoggedIn(user) },
onFailure(err) { showError(err) },
mfaRequired() { showMFA() }, // should not call onSuccess
}); Becomes: try {
session = await user.authenticateUser(...);
} catch (err) {
if (err === CognitoUser.MFA_REQUIRED_ERROR) { // or CognitoError.isMFARequired(err)?
showMFA();
} else {
showError(err);
}
} Though that is a bit ugly. Maybe resolve with a status code if we can (eg it should also resolve the callback) The other wart is |
Promises please! I'd love to be able to use them like I do with the rest of aws-sdk-js: Sign-up page action handlers calling my "service" that handles all user related auth:
UserData (service / provider) class
or
|
Definitely interested in anything that helps developers since developers seem to wrap calls in promises anyway #79 Backwards compatibility as you pointed out is a requirement, we don't want people to change their code. |
@itrestian I just wanted to pass along a couple links regarding promises and keeping backwards compatibility as related to what the aws-sdk-js did to accomplish this. First please check out the conversation for this github issue for aws-sdk-js where this was discussed and the beginnings for promises: Here's an AWS blog post covering this: Basically, what they did was if a callback function is not provided as the last arg then the function returns an AWSRequest object which has a .promise() function available. |
@paulsson The reason they had to do it that way was they were already returning an |
Thanks for the explanation @simonbuchan. Just seems like consistency among the SDK would be desired. I'm sure whatever is implemented will be a good fit with the rest of the SDK. |
I'm writing tests for the SDK here, once I've got good coverage I (and AWS!) can be more confident that doing this won't break usage. The big part will be All the rest looks like they could be done pretty quick. |
How are you getting on Simon? I'd like to be able to use Promises for this library too, but dont have enough experience to tackle the translation myself at the moment. |
@fatherdougal I want to finish getting test coverage in, since this would be more of a rewrite than the ES6 port I did for webpack in #108, but I'm making progress on that, see #154 |
It has been quite some time since this was updated, is there a status update? |
+1 for Promises, would it be possible to fork a WIP branch? |
Any news on the promise based function ? AWS.DynamoDB.DocumentClient() can return promises so aws cognito should be able to do the same. Any ETA ? |
Is promise supported yet? |
? |
Hey, any news :) ? |
Any news on this? I'm also interested in using Promises for this API. |
These async node callbacks are a mess. I just spent all afternoon wondering why this happens:
There is nothing anywhere to indicate that this is an async callback. For somebody who is new to JavaScript and doesn't know about NodeCallback this is a pain. I've just wrapped it in a promise but it would be nice by default. The docs or examples could be a bit more enlightening at the very least... |
I'm having the same concerns... every way of coding these promises in seemingly the correct manner, gives me all kinds of grief, with the main one being 'Callback is not a function.' :( What can we do here... I'm assuming most of my users will use the provided Login with Facebook, or Login with Google, and save me a tonne of trouble authenticating through the signUp, verify, process... but I still need it for the odd user who doesn't have FB or Google, but it seems that AWS doesn't like people writing new code. |
You can have a look at AWS Amplify which exposes a higher order auth component for this SDK. Maybe that can suit your use case. Also note that we will continue developing this library in the AWS Amplify repo. |
The current callbacks are a mess of node-style and callback objects, and are often immediately invoked, a problem for re-entrancy. I propose all callback accepting methods are updated to return a
Promise
and to make the callback argument optional.With all the current lib dependencies, adding a dependency for global
Promise
or polyfill should not be a big deal.There is a growing expectation that async methods return a
Promise
, they compose far better, and the proposed (and available now with babel)async / await
language feature make them as simple to use as synchronous methods:With callback object styles, I currently only propose making
onSuccess
andonFailure
optional, other callback properties can still make sense (but probably should be broken into multiple calls later):OLD PRE-ES6 CODE Strawman implementations (untested)
A minimal (hand-written) diff for hybrid node style and Promise returning:
Simply wrapping with
polygoat
:Rewriting using AWS SDK promise support and hybrid-izer wrapper:
The text was updated successfully, but these errors were encountered: