How to consume a Promise from a service (native script / firebase)? - javascript

I have a userService that calls firebase.login() which returns a result of type Promise<User>. It is called like this:
firebase.login( { config...
})
.then (function (result) { /* use result */},
function (error) { /* use error */ });
Elsewhere in the project, in a UI component, I need to react to the outcome of the login (i.e. success or error). I do not want to put any routing or similar logic into the user service, but rather have the other component control what happens next.
How is that done? How can another component react to it?
The component mentioned above is a class called LoginPage. It has a Login button which should start the Firebase login. The button is linked to a function (also called login()) in the LoginPage class.
XML:
<Button [text]="Sign in" class="submit-button" (tap)="login()"></Button>
login.component.ts
login() {
this._userService.login(this.user)
.then(function (data) {
/* go to next screen */
});
}
The above is obviously wrong, as the then clause will always be executed, regardless of the success or failure of the login.
Here is the login function in the userService:
#Injectable()
export class UserService {
login(user: User) {
firebase.login({
type: firebase.LoginType.PASSWORD,
email: user.email,
password: user.password
})
.then( function (result) {
console.log("Successful Login! " + JSON.stringify(result));
return result;
}, function (error) {
console.log(error);
return error;
});
}

UserService login method should return a promise to make it available for chaining:
login(user: User) {
return firebase.login(...)...
}
In the original above login error was already caught, this leaves the promise with resolution that can be either a result or an error.
The preferable way to handle errors here is to not catch the error in the service itself. We always want to know if login request was successful or not.
login(user: User) {
return firebase.login(...)
// second callback is optional if we don't need to log errors
.then( function (result) { ... }, function (error) {
console.log(error);
return firebase.Promise.reject(error);
});
}
This way an error can (and also should, Angular 2 will throw an error if there are uncaught promises) be caught and handled:
login() {
return this._userService.login(this.user)
.then(function (data) {
/* go to next screen */
})
.catch(function (error) { ... });
}
It is always preferable to return promises, at least for testing purposes.

Related

No responses defined for platform: DIALOGFLOW_CONSOLE

I've had this problem for almost a day and I don't know what else to do to solve it.
Dialogflow Fulfillment in Dialogflow ES just doesn't want to make any HTTP calls at all. I'm always getting this error: No responses defined for platform: DIALOGFLOW_CONSOLE
My entired code is below. The function that crash everything is:
function simpleGet(requestUrl) {
axios.get(https://eo1lbzchsaeazi9.m.pipedream.net/)
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
}
function simpleGet(requestUrl) {
axios.get(https://eo1lbzchsaeazi9.m.pipedream.net/)
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
}
sorry, there is some context missing here.
do you see the error message when trying to use fullfilments (ie. one API call to get on a backend an answer to a customer interaction?
Also, another clarifying question - is it Dialogflow ES or CX?
I've seen some developers struggling with this error and some of them fixed it by updating the package for fulfillments as described here: https://github.com/dialogflow/dialogflow-fulfillment-nodejs/issues/322

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;
})

How to get data from axios call in redux action? React JS search project

I have a search of weather for some cities. I would like to create info modal when a user tries to find a city that is not in the base. In this case I receive 404 error from my API.
I fetch the data every time when user click on search button. I use axios to do it and whole project is based on React and Redux. Everything is clear for me but I have a problem with pass valid response to payload.
How should I do it? In an another file and use react component lifecycle?
action.js
export function fetchWeather(city) {
const url = `${ROOT_URL}&q=${city}`;
axios.get(url)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
return {
type: FETCH_WEATHER,
payload: request
};
}
In your example the return will be called before Axios completes it's API call, because it's asynchronous. One solution to this is to put the return inside the .then like this:
export function fetchWeather(city) {
const url = `${ROOT_URL}&q=${city}`;
axios.get(url)
.then(function (response) {
// won't get called until the API call completes
console.log(response);
return {
type: FETCH_WEATHER,
payload: response.data
};
})
.catch(function (error) {
// won't get called until the API call fails
console.log(error);
return {
type: FETCH_WEATHER_ERROR,
payload: error
};
});
}
You should also return an error in the catch if the API call is unsuccessful.
In your snippet, request will always be undefined because axios.get is an async operation and return happens before axios.get finishes execution. You do something like this:
export async function fetchWeather(city) {
try {
const request = await axios.get(`${ROOT_URL}&q=${city}`);
// server returned a 2XX response (success)
return {
type: FETCH_WEATHER,
payload: request
};
} catch(error) {
// Network failure or 4XX or 5XX response.
return {
type: FETCH_WEATHER_FAIL
payload: error
}
}
}

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

Adapter error when connection is lost

When my application loses the internet connection, I get an error coming from the adapter and I'm not sure why it does that.
Error: Adapter operation failed
at new Error (native)
at Error.EmberError (http://localhost:5966/assets/vendor.js:25883:21)
at Error.ember$data$lib$adapters$errors$$AdapterError (http://localhost:5966/assets/vendor.js:66151:50)
at ember$data$lib$system$adapter$$default.extend.handleResponse (http://localhost:5966/assets/vendor.js:67455:16)
My application adapter looks like this:
export default DS.JSONAPIAdapter.extend(DataAdapterMixin, {
host: config.apiUrl,
handleResponse(status, headers, payload) {
if (status === 422 && payload.errors) {
return new DS.InvalidError(payload.errors);
}
return this._super(...arguments);
}
});
The error action in my application route never gets triggered.
export default Ember.Route.extend({
actions: {
error(error, transition) {
console.log(error, transition); //Never displayed
}
}
});
I'm making the call to the store in my controller.
export default Ember.Controller.extend({
actions: {
getUsers() {
this.get('store').findAll('user').then((users) => {
this.set('users', users);
});
}
}
});
Any idea how to fix this error and trigger the error hook in my route?
Thanks
I think you have to catch the error yourself so it doesn't get caught by the ember data implementation.
getUsers() {
this.get('store').findAll('user').then((users) => {
this.set('users', users);
}).catch((error) => {
// Add some custom error handling or do nothing to prevent the exception from getting thrown
});
}
Also your error hook in the route will only get fired when a promise in a transition (for example in one of the model hooks) rejects. If you have a promise in a controller you have to trigger the action/event yourself.

Categories