24 July 2019
Angular (39) -- NgRx Effects
by Jerry Zhang
LeetCode Day 19: P155. Min Stack (Easy)
题目:
设计一个stack, 支持push, pop, top, 并且能在O(1)时间内找出最小值。
我的思路:
用LinkedList, 每次push, pop时更新一下最小值。
答案:
public class E_155_MinStack {
/** initialize your data structure here. */
int min = Integer.MAX_VALUE;
Stack<Integer> stack;
public E_155_MinStack() {
stack = new Stack<>();
}
public void push(int x) {
if (x <= min) {
stack.push(min);
min = x;
}
stack.push(x);
}
public void pop() {
if (stack.pop() == min) {
min = stack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return min;
}
}
如果是更小的值,就push两次,如果当前pop的是最小值,就pop两次。
Angular: NgRx Effects
Auto Logout
In auth.service.ts
:
setLogoutTimer(expirationDuration: number) {
this.tokenExpirationTimer = setTimeout(() => {
this.store.dispatch(new AuthActions.Logout());
}, expirationDuration);
}
clearLogoutTimer() {
if (this.tokenExpirationTimer) {
clearTimeout(this.tokenExpirationTimer);
this.tokenExpirationTimer = null;
}
}
In auth.effects.ts
, set up the timer when we need:
In authSignup effect, Add this code:
tap(resData => {
this.authService.setLogoutTimer(+resData.expiresIn * 1000);
}),
Then, the complete authSignup
effect becomes the following:
@Effect()
authSignup = this.actions$.pipe(
ofType(AuthActions.SIGNUP_START),
switchMap((signupAction: AuthActions.SignupStart) => {
return this.http.post<AuthResponseData>(
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=AIzaSyCQUonbyGcWNNCk-jS2WWkgpR3U0TtkIdA',
{
email: signupAction.payload.email,
password: signupAction.payload.password,
returnSecureToken: true
})
.pipe(
tap(resData => {
this.authService.setLogoutTimer(+resData.expiresIn * 1000);
}),
map(resData => {
return handleAuthentication(
+resData.expiresIn,
resData.email,
resData.localId,
resData.idToken
);
}),
catchError(errorRes => {
return handleError(errorRes);
})
);
})
);
Also add this timer in the authLogin
and autoLogin
effects.
@Effect()
authLogin = this.actions$.pipe(
ofType(AuthActions.LOGIN_START),
switchMap((authData: AuthActions.LoginStart) => {
return this.http.post<AuthResponseData>(
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=AIzaSyCQUonbyGcWNNCk-jS2WWkgpR3U0TtkIdA',
{
email: authData.payload.email,
password: authData.payload.password,
returnSecureToken: true
}).pipe(
tap(resData => {
this.authService.setLogoutTimer(+resData.expiresIn * 1000);
}),
map(resData => {
return handleAuthentication(
+resData.expiresIn,
resData.email,
resData.localId,
resData.idToken
);
}),
catchError(errorRes => {
return handleError(errorRes);
}) );
}),
);
@Effect()
autoLogin = this.actions$.pipe(
ofType(AuthActions.AUTO_LOGIN),
map(() => {
const userData: {
email: string;
id: string;
_token: string;
_tokenExpirationDate: string;
} = JSON.parse(localStorage.getItem('userData'));
if (!userData) {
return { type: 'DUMMY'};
}
const loadedUser = new User(
userData.email,
userData.id,
userData._token,
new Date(userData._tokenExpirationDate)
);
if (loadedUser.token) {
// this.user.next(loadedUser);
const expirationDuration = new Date(userData._tokenExpirationDate).getTime() - new Date().getTime();
this.authService.setLogoutTimer(expirationDuration);
return new AuthActions.AuthenticateSuccess({
email: loadedUser.email,
userId: loadedUser.id,
token: loadedUser.token,
expirationDate: new Date(userData._tokenExpirationDate)
});
// const expirationDuration = new Date(userData._tokenExpirationDate).getTime() - new Date().getTime();
// this.autoLogout(expirationDuration);
}
return { type: 'DUMMY'};
})
);
When logging out, clear the timer
@Effect({dispatch: false})
authLogout = this.actions$.pipe(
ofType(AuthActions.LOGOUT),
tap(() => {
this.authService.clearLogoutTimer();
localStorage.removeItem('userData');
this.router.navigate(['/auth']);
})
);