Create an asynchronous function with react native - javascript

I have a function that retrieve asynchronously a password from the keychain.
In MyStaticClass
static getPassword() {
Keychain
.getGenericPassword()
.then(function(credentials) {
console.log('Credentials successfully loaded for user ' + credentials.username);
return credentials.password
}).catch(function(error) {
console.log('Keychain couldn\'t be accessed! Maybe no value set?', error);
});
}
I tried to call the function and receive the promise with this code but the result is undefined
MyStaticClass.getPassword().then((data) => {
alert(data);
});
I also tried this code and password was also undefined
static async login(){
const password = await MyStaticClass.getPassword();
alert(password);
}

You are missing return statement in getPassword method
return Keychain ...

Related

Async method always returning true

I am implementing a login functionality with firebase and React Native. The handleLogin method is always returning succeed(). If I remove the success(), I get :
[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'result2.failed')]
export default async function login(credentials) {
let result2= succeed();
result2 = await handleLogin(credentials.email, credentials.password);
if(result2.failed()){
return fail({password: "Login failed"});
}
else{
return succeed();
}
}
const handleLogin = async(email,password) => {
auth.signInWithEmailAndPassword(email, password)
.catch(function(error) {
console.log(error);
return fail("failed");
})
return succeed(); // or fail() in which case method always returns fail()
I have also tried using .then() but I keep getting object undefined error if I don't return succeed() or fail() in the end of handleLogin():
auth.signInWithEmailAndPassword(email, password)
.then(function(){return succeed();})
.catch(function(error) {
console.log("we fail"+error);
return fail("failed");
})
Its a known issue of the firebase. Similar thing happened to me on angular code.
I solved the problem by adding a return statement:
return auth.signInWithEmailAndPassword(email, password).then(function(){return succeed();}).catch(function(error) { return fail("Login Attempt Failed\n"+error);})

Why does my async function always return false to the wrapper function?

I have an async function that triggers AWS Amplify to send a password reset code to a user.
export async function forgotPassword(username) {
console.log('forgotPassword')
return Auth.forgotPassword(username)
.then(data => {
console.log('aws reset password request success')
console.log(data)
})
.catch(error => {
console.log('error with call to AWS forgotPassword fncn')
})
}
Here is a wrapper function that calls the function above...
forgotPassword(email).then(success => {
if (success) {
console.log('successful forgot password action')
Vue.prototype.$notification.success({
message: 'Forgot password action success',
description: 'You have successfully submitted a password refresh request!',
})
}
if (!success) {
console.log('failed forgot password action')
}
})
I know that the inner function runs successfully because my console log statement for debugging that method does indeed execute and print 'aws reset password request success'.
However, my wrapper function always detects a failure in the aws function because I see that the wrapper function enters the !success clause. Why is this? I am guessing there is a syntax error with my async await code in the inner aws function
Update, based on the answers I've read so far, I updated my inner function as follows.
export async function forgotPassword(username) {
console.log('forgotPassword')
try {
const data = await Auth.forgotPassword(username)
console.log('aws password reset request success')
console.log(data)
return true
} catch (error) {
console.log('error with call to AWS forgotPassword fncn')
notification.warning({
message: error.code,
description: error.message,
})
}
}
It appears to work properly.
This is because your promise, returned by the first function, resolves to undefined. As you chain a .then to the initial promise, you should make sure to return the value that promise should resolve with:
.then(data => {
console.log('aws reset password request success')
console.log(data)
return data; // or: return true;
})

Async Await | Can't have server wait for response from database before using authenification

So i'm having a problem where i'm attempting to have an async call to my database to check if the username and password of an account exist before then checking to see if they are valid.
I'm running into the problem that the server skips my database call and then proceeds to the check before the information from the database is grabbed.
The code:
class HandlerGenerator {
login (req, res) {
let username = req.body.username;
let password = req.body.password;
let checkUsername = "";
let checkPassword = "";
var lData = {
username: req.body.username,
password: req.body.password
};
// For the given username fetch user from DB
var db = req.db;
var getUser = async () => {
var result = await (
User.findOne(lData , function(err, userLogin){
if(err){
console.log(err);
return
}
console.log(userLogin);
console.log("------====----");
console.log(userLogin.username);
checkUsername = userLogin.username;
checkPassword = userLogin.password;
console.log("------====----");
console.log(checkUsername);
console.log(checkPassword);
})
);
console.log("--00--");
console.log('result' + result)
return result;
};
console.log("does this work?");
if (username && password) {
console.log("------==2==----");
console.log(checkUsername)
console.log(checkPassword)
if (username === checkUsername && password === checkPassword) {
let token = jwt.sign({username: username},
config.secret,
{ expiresIn: '24h' // expires in 24 hours
}
);
// return the JWT token for the future API calls
res.json({
success: true,
message: 'Authentication successful!',
token: token
});
} else {
res.send(403).json({
success: false,
message: 'Incorrect username or password'
});
}
} else {
res.send(400).json({
success: false,
message: 'Authentication failed! Please check the request'
});
}
}
index (req, res) {
res.json({
success: true,
message: 'Index page'
});
}
}
When I run this the "Does this work?" Comment always runs first and i'm confused on what I am messing up
You have two main issues here.
First, async returns an AsyncFunction, which returns a Promise when called. This means that at this point, nothing in getUser has been executed. Not only you need to actually call getUser to start running what is inside it, but you also need to await the result, otherwise you have absolutely no guarantee that the execution will be over.
Instead of going through this trouble, making your login function async seems a more reasonable choice, as you are trying to do asynchronous operations inside it. You could then remove the getUser function and only keep the var result = await User.findOne(....) part.
The other issue, as multiple persons said in the comments, is that you need to await on a Promise.
Looking at your function call, it looks like your findOne functions uses a callback rather than a promise. Do check the documentation, some libraries support both and might indeed return a promise if you do not pass in any callback.
If it does, you should not pass any callback. The result of the "awaited" call should be userLogin.
Otherwise, wrapping the function so that it returns a promise is straightforward.
The basic pattern is as follows
// this is the function that we want to wrap
function funcToWrap(someParam, callback) {
// does stuff
callback(null, "some result");
}
// this is the wrapper
function wrappedFunction(someParam) {
return new Promise((resolve, reject) => {
funcToWrap(someParam, (err, res) => {
if (err === null) {
reject(err);
} else {
resolve(res);
}
});
});
This transforms your callback-based function into a promise-based one. You can then of course await on wrappedFunc and use it as any other promise.
This is such a common pattern that a lot of libraries already implement this functionality. For example, the Promise library Bluebird provides a promisify function which does exactly this.
http://bluebirdjs.com/docs/api/promise.promisify.html
So instead of writing all of this yourself, you could simply write
var wrappedFunction = Promise.promisify(funcToWrap);

Add a callback to Firebase Login Function

I am fairly new to React and the use of Firebase. Right now I have a Firebase.js file where I have stored and exported all of my functions and consts. This is what it looks like:
export const auth = firebase.auth();
export function performLogin(email, password) {
auth.signInWithEmailAndPassword(email, password).then(function(data) {
//Works
}).catch(function(error) {
//Does not work
});
}
So, I have this login.js that I am calling performLogin from, and I was wondering what would be the best way of doing this? How can I create a callback, or at least read any kind of return message? This is how I call performLogin:
clickLogin(e){
e.preventDefault();
performLogin(this.state.email, this.state.password);
}
And this works, as the console output tells me if the login was successful or not. However, I want to be able to use this function in order to retrieve the login status, and then determine wether or not I should prompt an error message or push the user to the admin dashboard. How would I do this?
Is it possible to call performLogin like this?
performLogin(this.state.email,this.state.password,(callback)){
if (callback == true) { //Success } else { //Error }
}
Your performLogin function could take a third parameter, a callback function that lives where your clickLogin() method lives:
export function performLogin(email, password, callback) {
auth.signInWithEmailAndPassword(email, password).then(function(data) {
//Works
callback(data);
}).catch(function(error) {
//Does not work
callback({ error });
});
}
loginResult(result) {
if(result.error) {
//failed
} else {
//logged in
}
}
clickLogin(e){
e.preventDefault();
performLogin(this.state.email, this.state.password, this.loginResult);
}
Or you could return the promise that signInWithEmailAndPassword() returns and handle it in the component.
export function performLogin(email, password) {
return auth.signInWithEmailAndPassword(email, password);
}
clickLogin(e){
e.preventDefault();
performLogin(this.state.email, this.state.password)
.then(result => //logged in)
.catch(error => //failed)
};
Take a look at the function onAuthStateChanged from "firebase/auth" package.
Here is a link to the docs:
https://firebase.google.com/docs/auth/web/manage-users

Failure to run angular-spotify method in Ionic service

I've been struggling with handling retrieval of Spotify data in an Ionic service all day, and something that was working earlier now suddenly doesn't.
I have my login script set up in a service, and it is all working fine. However, after the console.log('updateInfo() called'); method inside updateInfo, the program will skip the rest of the function, avoiding gathering the data from Spotify.
This is the entire service so far:
.factory('SpotifyService', function ($cordovaOauth, Spotify) {
var currentUser = {},
userId = '';
function login() {
console.log('login() called');
$cordovaOauth.spotify('583ac6ce144e4fcb9ae9c29bf9cad5ef', ['user-read-private', 'playlist-read-private']).then(function (result) {
window.localStorage.setItem('spotify-token', result.access_token);
Spotify.setAuthToken(result.access_token);
}, function (error) {
console.log("Error ->" + error);
});
}
function updateInfo() {
console.log('updateInfo() called');
Spotify.getCurrentUser().then(function (data) {
console.log('Gathering data');
currentUser = data;
userId = data.id;
console.log("CURRENT USER: " + userId + " - (" + currentUser + ")");
console.log('Done updating');
});
}
return {
getUser: function () {
console.log('SpotifyService.getUser() called');
var storedToken = window.localStorage.getItem('spotify-token');
if (storedToken !== null) {
console.log('Token accepted');
currentUser = updateInfo();
console.log('getUser function returns: ' + userId + " - (" + currentUser + ")");
//currentUser = Spotify.getCurrentUser();
} else {
console.log('getUser else accessed');
login();
}
return currentUser;
}
};
})
Any ideas as to why the Spotify.getCurrentUser() method won't run?
It seems like your issue is with promises. If Spotify.getCurrentUser() returns a promise you wouldn't know what the error is because you haven't defined a catch statement. You should read Promises in Angular Explained as a Cartoon for a simple and clear explanation of promises.
Revise your code to add a catch statement:
Spotify.getCurrentUser()
.then(function (data) {
...
})
.catch(function(error){
console.log(error);
});
Every time you use promises like $cordovaOauth.spotify() or Spotify.getCurrentUser() you have to define .catch block, that will help you debugging.
Add .catch block to the getCurrentUser() function call to track down your error and i would also recommend changing error callback pattern in auth function call into .catch block as well
.catch(function(error){
console.log(error);
});

Categories