I'm receiving data from api using axios, and i want to add error handling to it, i have different messages on different error codes received(401,400,503 etc), but i also want to set timeout of 1 min on 401 errors 2min on error code 500 etc.is that possible using axios without importing axios retry ? I tried coming up with a solution by using interceptors but then spread.js which is imported with axios spams the error in console log and causes browser freeze.I used the following code for timeout in interceptors
axios.interceptors.response.use(function (response) {
// Do something with response data
console.log(response);
return response;
}, function (error) {
// Do something with response error
if(error.response.status===401){
setTimeout(function (){
console.log(error.response.status===401);
return Promise.reject(error);
},10000);
}
if(error.response.status===503){
setTimeout(function (){
console.log(error.response.status===503);
return Promise.reject(error);
},30000);
}
if(error.response.status===500){
setTimeout(function (){
console.log(error.response.status===401);
return Promise.reject(error);
},50000);
}
});
You need to return your setTimeout() in order for it to work. You could use else-ifs in your code to make it more efficient
axios.interceptors.response.use(function(response) {
console.log(response);
return response;
}, function(error) {
if (error.response.status === 401) {
return setTimeout(function() {
console.log(error.response.status === 401);
return Promise.reject(error);
}, 10000);
}
else if (error.response.status === 503) {
return setTimeout(function() {
console.log(error.response.status === 503);
return Promise.reject(error);
}, 30000);
}
else if (error.response.status === 500) {
return setTimeout(function() {
console.log(error.response.status === 401);
return Promise.reject(error);
}, 50000);
}
else {
return Promise.reject(error)
}
});
Related
I'm using this service worker for caching and offline mode.
when I am already on any existing page of my website and I request a non-existent page, the Offline page is served instead of the 404 page.
If, on the other hand, I close and reopen the browser and immediately request a non-existent page of my website, the 404 page is served correctly.
I suspect it has to do with these last few lines of the code
if(!matching || matching.status == 404) { return cache.match("/service/offline/"); but i don't know how to fix this problem. Can you help me please?
Here's the full service worker:
self.addEventListener("install", function(event) {
event.waitUntil(preLoad());
});
var preLoad = function(){
console.log("Installing web app");
return caches.open("offline").then(function(cache) {
console.log("caching index and important routes");
return cache.addAll([
'/assets/css/about.min.css',
'favicon.ico',
'/assets/js/script.js',
'manifest.webmanifest.webmanifest',
'/',
'/about/',
'/contact/',
'/service/offline/'
]);
});
};
self.addEventListener("fetch", function(event) {
event.respondWith(checkResponse(event.request).catch(function() {
return returnFromCache(event.request);
}));
event.waitUntil(addToCache(event.request));
});
var checkResponse = function(request){
return new Promise(function(fulfill, reject) {
fetch(request).then(function(response){
if(response.status !== 404) {
fulfill(response);
} else {
reject();
}
}, reject);
});
};
var addToCache = function(request){
return caches.open("offline").then(function (cache) {
return fetch(request).then(function (response) {
console.log(response.url + " was cached");
return cache.put(request, response);
});
});
};
var returnFromCache = function(request){
return caches.open("offline").then(function (cache) {
return cache.match(request).then(function (matching) {
if(!matching || matching.status == 404) {
return cache.match("/service/offline/");
} else {
return matching;
}
});
});
};
I'm having trouble getting redirects to work after accepting a get request from Axios. I do know that the request is being sent and that it at least gets some response from the URL route,
when i console response.data.redirect it return undefined
const onSubmitHandler = (e) => {
e.preventDefault()
axios.get('/get/user')
.then(function (response) {
if (response.data.redirect == '/' || response.data.redirect == '/login' ) {
window.location = "/login"
} else {
console.log(response.data)
}
})
.catch(function(error) {
window.location = "/login"
})
}
I received status code 302 but it automatically redirects to the page without page refresh shows the redirected page on the same page in a div section.
Anyone knows how can I use interceptor with Axios such that if the status code fall in 200 series then does something else page refresh. I checked the Axios docs but there is no implementation
Try this for interceptors
axios.interceptors.response.use(
response => {
return response.data;
},
err => {
//return new Promise((resolve, reject) => {
//err.response.status for getting error status
// }
throw err;
});
}
);
I have the below code which is binding to an LDAP server and I want to return the user that I have added "ab" within the "interviewees" group (code taken from ldapjs client api page). I can see I am getting back a response from the server with the expected EventEmitter object. I am expecting to see information about the user when calling logging console.log() on the searchEntry object. I appear to have no searchEntry objects. Is my DN for my user correct? I am currently unsure whether the issue is with my query and I am not getting any data back or whether I am failing to process the response correctly?
const client = ldap.createClient({ url: 'ldap://' + LDAP_SERVER + ':' + LDAP_PORT });
// Connect and bind to the Active Directory.
const connectToClient = async () => {
const secret = LDAP_SECRET_KEY;
return await new Promise((resolve, reject) => {
client.bind(LDAP_USER, secret, function (err, res) {
if (err) {
console.error(err);
reject('Failed to connect to LDAP server');
} else {
resolve('Connected to LDAP server');
}
});
});
};
onst searchADForUser = async () => {
return await new Promise((resolve, reject) => {
client.search('CN=ab,OU=interviewees,OU=Users,OU=interview,DC=interview,DC=workspace,DC=com', function (err, res) {
if (err) {
console.error(err);
reject('Error searching LDAP server');
} else {
res.on('searchEntry', function (entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
});
resolve(res);
}
});
});
};
const handler = async (event) => {
try {
return responses.success(
await connectToClient().then(async function(event) {
console.log(event);
await searchADForUser().then(function(event) {
console.log(event);
}).catch(function(event) {
console.log(event);
})
}).catch(function(event) {
console.log(event);
})
);
} catch (err) {
console.error(err);
return responses.error(err);
} finally {
client.unbind();
}
};
The active directory structure is below
The central issue I was having was understanding how to process the returned EventEmitter object from the search function. I need to add to an array on each searchEntry event and then return that entry in my resolve callback function only once the end event had occurred. The code above was calling resolve immediately and hence no searchEntry events or the end event had been processed yet.
Code I am now using below:
function (err, res) {
if (err) {
console.error(err);
reject(new Error('Error retrieving users from Active Directory'));
} else {
const entries = [];
res.on('searchEntry', function (entry) {
entries.push(entry);
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
if (result.status !== 0) {
reject(new Error('Error code received from Active Directory'));
} else {
resolve(entries);
}
});
}
}
With axios the code is:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => err);
}
And then I'm using this with redux-saga like this:
function* createBlaBlaFlow(action) {
try {
const response = yield call(createBlaBla, action.payload);
if (response) {
yield put({
type: CREATE_BLA_BLA_SUCCESS
});
}
} catch (err) {
// I need the error data here ..
yield put({
type: CREATE_BLA_BLA_FAILURE,
payload: 'failed to create bla-bla'
});
}
}
In case of some error on the backend - like invalid data send to the backend - it returns a 400 response with some data:
{
"code":"ERR-1000",
"message":"Validation failed because ..."
"method":"POST",
"errorDetails":"..."
}
But I don't receive this useful data in the catch statement inside the saga. I can console.log() the data in the axios catch statement, also I can get it inside the try statement in the saga, but it never arrives in the catch.
Probably I need to do something else? ... Or the server shouldn't return 400 response in this case?
So, I came up with two solutions of this problem.
===
First one - very dump workaround, but actually it can be handy in some specific cases.
In the saga, right before we call the function with the axios call inside, we have a variable for the errors and a callback that sets that variable:
let errorResponseData = {};
const errorCallback = (usefulErrorData) => {
errorResponseData = usefulErrorData;
};
Then - in the axios method we have this:
export const createBlaBla = (payload, errCallback) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => {
if (err && err.response.data && typeof errCallback === 'function') {
errCallback(err.response.data);
}
return err;
});
}
This way, when we make request and the backend returns errors - we'll call the callback and will provide the errors from the backend there. This way - in the saga - we have the errors in a variable and can use it as we want.
===
However, another solution came to me from another forum.
The problem I have is because in the method with the axios call I have catch, which means that the errors won't bubble in the generator. So - if we modify the method with the axios call like this:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
}
Then in the catch statement in the saga we'll have the actual backend error.
Hope this helps someone else :)
In your API call you can do the following:
const someAPICall = (action) => {
return axios.put(`some/path/to/api`, data, {
withCredentials: true,
validateStatus: (status) => {
return (status == 200 || status === 403);
}
});
};
Please note the validateStatus() part - this way when axios will encounter 200 or 403 response, it will not throw Error and you will be able to process the response after
const response = yield call(someAPICall, action);
if (response.status === 200) {
// Proceed further
} else if (response.status === 403) {
// Inform user about error
} else {
...
}
What I want is to make GET http request in my provider, wrap http call in Observable.create and return Observable object, then in my component, resolve that Observable. I tried something, can someone tell me if it is ok (I can't test at the moment so don't know if it works)? If it's not ok, can someone guide me what is the best practice in Ionic 3, to do http call and handle response (success, failure)?
In provider:
public getUsers(credentials):Observable<any> {
if("some custom condition not satisfied")
return Observable.throw("ERROR);
return Observable.create(observer => {
this.http.get(API_URL + '/users').subscribe(
(response) => {
observer.next(response);
observer.complete();
},
(error)=> {
return Observable.throw(error);
});
});
}
then in component:
this.myProvider.login().subscribe(response => {
if (response.status == 403) {
this.loading.dismiss();
console.log("Access denied");
}
this.loading.dismiss();
this.nav.setRoot('MainPage');
},
error => {
this.loading.dismiss();
console.log(error);
});