React clear LocalStorage and Asyncstorage in one Component - javascript

is it possible to clear the LocalStorage and AsyncStorage in one Component?
I want to clear the Storage if the 401 error displayed.
Need to share this for React and React-Native, is there a way to solve it?
I guess with try and catch will not work.
Hope someone can help me to fix this.
import 'whatwg-fetch';
import AsyncStorage from '#react-native-async-storage/async-storage';
async function clearMobile(){
await AsyncStorage.clear();
}
const clearWeb = () => {
localStorage.clear();
}
export const authFetch = (originalFetch => {
return (...args) => {
const result = originalFetch.apply(this, args);
return result.then(
(response) => {
if (!response.ok && response.status === 401)
try {
clearMobile();
}
catch {
clearWeb();
}
finally {
window.location.reload();
}
return response;
}
);
};
})(fetch);
export default authFetch;

You want to clear both at the same time, both functions must be used inside the try block. try...catch
try {
clearMobile();
clearWeb();
}
catch (error) {
console.log(error);
}
In this way, you will have cleaned both of them. And if there is a bug, you will debug it.
I'm sorry if the question is not what I understood.

Related

SvelteKit UnhandledPromiseRejection with strange TLS Connection error

I have here a strange collection of error, for which i canno't find any solutions on the internet ( maby i'm just bad with google ).
I created a website, with the following files/folder tree:
With this setup i first got this error message:
Client network socket disconnected before secure TLS connection was established.
Which I didn't find any solution for other then reload the page.
After deciding handling the error myself i tried this:
api.js
import axios from 'axios';
import axiosRetry from 'axios-retry';
const base = process.env['API_ENDPOINT'];
axiosRetry(axios, { retries: 5 });
async function send({ path }) {
let pages = 0;
let resp;
try {
resp = await axios.get(`${base}/${path}`);
} catch (error) {
throw error;
}
if ('X-WP-TotalPages' in resp.headers) {
pages = resp.headers['X-WP-TotalPages'];
}
return {
pages: pages,
body: resp.data
};
}
export async function get(path) {
return send({ method: 'GET', path });
}
And i call it in (for example) landing.js:
import { writable } from 'svelte/store';
import { browser } from '$app/env';
import * as api from '$lib/api';
let loading = false;
let posts = [];
const list = writable({
loading,
posts
});
export default {
subscribe: list.subscribe,
async fetchNews() {
if (loading) return {};
loading = true;
list.set({ loading, posts });
let lang = 'de';
if (browser) {
lang = localStorage.getItem('lang') || 'de';
}
try {
const res = await api.get(`posts?filter[lang]=${lang}&per_page=4&_embed`);
} catch (error) {
throw error;
}
posts = await res.body;
posts.map((post) => {
if (post._embedded['wp:featuredmedia'])
post.image = post._embedded['wp:featuredmedia'][0].source_url;
else post.image = '/news/news_placeholder.png';
});
loading = false;
list.set({ loading, posts });
}
};
Now the new error is something like this:
[UnhandledPromiseRejection: This error originated either by throwing
inside of an async function without a catch block, or by rejecting a
promise which was not handled with .catch(). The promise rejected with
the reason "Test".] { code: 'ERR_UNHANDLED_REJECTION' }
Maybe I'm just an idiot right, but i need really some help here!
Thanks in advance for this.
Try wrapping the whole function body in try {...}, instead of the const res = await api.get... line and observe where exactly the error happens.

axios dosen't catch error with axios-auth-refresh library

I am trying to use axios-auth-refresh library installed by npm. I stucked at problem i can't resolve. According to documentation i made code like this:
const refreshAuthLogic = (failedRequest) => {
let tokenData = JSON.parse(localStorage.getItem("REACT_TOKEN_AUTH"));
if (tokenData) {
return axios
.post(`${process.env.REACT_APP_API_URI}/Login/refresh-token`, {
departmentId: tokenData.departmentId,
jwtToken: tokenData.jwtToken,
userId: tokenData.userId,
})
.then((response) => {
console.log(response);
localStorage.setItem("REACT_TOKEN_AUTH", JSON.stringify(response.data));
failedRequest.response.config.headers["Authorization"] =
"Bearer " + response.data.jwtToken;
return Promise.resolve();
})
.catch((err) => {
console.log(`refreshed failed`);
logout();
return Promise.reject(err);
});
} else {
logout();
}
};
createAuthRefreshInterceptor(axios, refreshAuthLogic, {
statusCodes: [401],
});
Everything works almost perfect but catch never fire up so i can't logout user when refresh token expired. I get answer from api with 401 code but even if i try to put simple console log in .catch() nothing happen.
I have no idea what am i doing wrong? any ideas how to add logout() function to that code that will work?
Thanks to Sangam Rajpara, I've found a solution. You need to create a separate instance of axios.
const requestToken = axios.create();
Then use interceptors for the created instance. You can read about them on the axios page. Something like this:
requestToken.interceptors.response.use(
(res) => res,
(err) => {
// your log out action
logout();
return err;
}
);
Then, in your code instead of axios, use the instance that you created:
requestToken
.post(`${process.env.REACT_APP_API_URI}/Login/refresh-token`, {
departmentId: tokenData.departmentId, ...
You don't really need that "if" logic anymore

Throwing error from subscription/observable - Angular2+

I am attempting to throw an error from my observed function, such that I can access the err part of my subscription, but I cannot seem to get through to that part.
I'm not sure how to do it via the map way, but here is a different way:
import { Observable, of, throwError } from 'rxjs';
ngOnInit() {
this.getObs().subscribe(data => {
console.log(data);
}, err => {
console.log(err);
});
}
getObs() {
const observable = of(6);
const isError = true;
if (isError) {
return throwError("Is an error!");
}
return observable;
}
Working example: https://stackblitz.com/edit/angular-mqp4qv?file=src/app/app.component.ts
Couple ways I would handle this. Heres one way using _throw
// auth.ts
import { _throw } from 'rxjs/observable/throw';
login( username, password ) {
const body = this.jsonifyData( username, password );
return this.http.post<any>( this.apiBaseUrl + '/auth', body )
.pipe(
map( res => {
if ( 'token' in res ) {
return res.token;
}
// Unsuccessful login returns error
return _throw( res ); // from import {_throw} from 'rxjs/observable/throw';
} )
);
}
The other would be to just catch the error in the login component
I think in your component's test spec you need to mock up your authService and the login procedure. This mock does not make http call, just throw an error via throwError(new Error('Either username or password were incorrect')) immediately if, say, password does not match some predefined value. Here is some example of how to test component-http service stuff, it is a bit outdated but still actual conceptually.

Rerun function on error and pass result up

I have separated my api call into three layers. The component, the repository, and the apihelper. I want the logic for refresh_tokens to be in apihelper.js. When I do this it seems like the apihelper runs again after getting the 401 response status but it never passes the data back up to the component. I know I could put the logic to rerun it in the component but that seems like it will end up being a lot of duplicate code as I add more calls. I feel like it's probably caused by my shallow understanding of javascript promises but I'm a javascript beginner.
Component
<script>
import breweryrepository from '#/repository/breweryrepository.js'
export default {
mounted() {
this._getTotalBreweries();
},
methods: {
_getTotalBreweries() {
breweryrepository.getTotalBreweries()
.then((response) => {
if(response.data)
{
this.totalNumberOfBreweries = response.data.totalBreweries;
}
})
}
},
data () {
return {
totalNumberOfBreweries: ''
}
}
}
</script>
Repository
import apihelper from '#/helpers/ApiHelper.js';
export default {
getTotalBreweries() {
return new Promise(function(resolve, reject) {
resolve(apihelper.apiCall('/brewery/totalnumber'));
});
}
}
Apihelper
import axios from 'axios';
var querystring = require('querystring');
import { store } from '../store/store.js';
import auth from '#/auth/auth.js'
export default {
apiCall(url) {
return axios.get(store.state.baseUrl + url, { 'headers': auth.getAuthHeader() })
.catch((error) => {
if(error.response.status == 401)
{
console.log("401 error, running refresh and apicall again");
auth.refreshToken();
this.apiCall(url);
}
})
}
}
Aaaaand I wasn't returning the call.
return this.apiCall(url);
Works now

Observable Shorthand

I'm wondering if there is a better way (read: shorter) to write the following function in Typescript/Angular2. I find myself in a situation a lot of times where I'm caching observable server data and returning the cached value if it exists. My way (below) seems to be a bit overkill.
getUser(){
return Observable.create(s => {
if(!this.user)
this.connection.identity((err, res) => {
this.user = res;
s.next(res);
s.complete();
})
else{
s.next(this.user);
s.complete();
}
});
}
This is a little shorter and it handles errors:
import "rxjs/add/observable/of";
import "rxjs/add/observable/bindNodeCallback";
import { Observable } from "rxjs/Observable";
...
getUser() {
return this.user ?
Observable.of(this.user) :
Observable.bindNodeCallback(
this.connection.identity.bind(this.connection),
res => this.user = res
)();
}

Categories