Catching errors with axios - ajax

I can not catch the error response with axios. How to do that?
I use something like:
axios
.post(...)
.then(response => {
console.log('Success: ', response)
}).catch(error => {
console.log('Error: ', error)
})
I see that the result of ajax request has 400 status code and the response body looks like {someField:["This field may not be blank"]} (Django backend). That's ok, I'm ready to process these errors in the catch handler.
But they go to the success handler instead. Why so? I see the following output in the console:
Success: Error: Request failed with status code 400
at createError (createError.js:16)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:77)
The success handler receives axios error object as the result. Why that may be and what to do next? This error object does not contain any usefull information.
UPD. Actually, the error object does contain the useful information, it contains the response object inside. So we can use:
axios
.post(...)
.then(response => {
if (response && response.response) {
console.log('This is also an error', response.response.status)
} else {
console.log('Success: ', response)
}
}).catch(error => {
console.log('Error: ', error)
})
But that looks super ugly.
The axios version is axios#0.16.2.
That's the big project, but I can not find any axios customizations.

Use Axios interceptors for the response. Check which status you want to force to fail as error so they go through the catch path whenever you receive said status code.
axios.interceptors.response.use(function (response) {
if (response.status === 400) {
return Promise.reject(response);
}
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
If you are not receiving the expected status code, you might change the way you check the response in the interceptor. You can check any of the elements that Axios response is structured.
axios.interceptors.response.use(function (response) {
if (response.statusText !== 'OK') {
return Promise.reject(response);
}
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});

Related

Neither onNext, nor onError is called when Angular HttpClient POST receives in 500

I am observing something that I cannot see/explain. I did talk to a second pair of eyes and did my due diligence googling. What am I missing - as the title says, onNext and onError aren't called, but onComplete is when back end returns HTTP500 (endpoint throws 500 for the purpose of testing angular error handling). Why?
Service:
delete(item: Item): Observable<any> {
return this.http.post(this.url("delete"), item, { headers: this.header });
}
Component:
this.itemDataService.delete(this.item)
.subscribe(
() => {
alert("result");
..;
},
err => {
alert("Error");
},
() => {
alert("complete");
...;
}
);
you probably have an interceptor swallowing your errors somewhere.. only way this could happen if that's the native http client.

Axios get request to Laravel endpoint from next.js

I have the following request to my laravel endpoint:
axios.get('http://localhost:8000/auth/login', {})
.then(function (response) {
console.log(response);
return {};
})
.catch(function (error) {
return {}
});
And my laravel endpoint set up as:
public function index() {
var_dump('login called.');die;
return response()->json(
[],
200
);
}
I Started my nextjs server (port 3000) and laravel server(8000), and when i browse to localhost:8000/auth/login in my browser I see "login called". however when I do that axios call, I get a status 200ok but no response data.
Request URL:http://localhost:8000/auth/login
Request Method:GET
Status Code:200 OK
Remote Address:127.0.0.1:8000
Referrer Policy:no-referrer-when-downgrade
Any idea what I am doing wrong?
Nothing is wrong with your code you are getting the response correctly, you see "login called" because you are accessing from a browser, therefore a browser has the cappability to render the html and you can see that.
But that axios call expects some json in return.
If you tweak the response a bit:
public function index() {
return response()->json(
['data' =>'Log in called'],
200
);
}
and if you twak axios response a bit
axios.get('http://localhost:8000/auth/login', {})
.then(function (response) {
console.log(response.data);
return {};
})
.catch(function (error) {
return {}
});
Inspect element open console and you will see 'Log in called'

Axios interceptor doesn't intercept on page load

I am implementing JWT into my Vue application for authorization and I refresh my tokens once they are used.
I have used axios interceptors so I can intercept every request to my API backend and this seems to work on login etc... but once I refresh the page the request is made as normal using the last token.
The problem is the axios interceptors don't seem to work at this point, so once the token has been used I can't update it with the new one.
Here's how I'm setting my interceptors:-
window.axios.interceptors.request.use(function (config) {
console.log("Sent request!");
return config;
}, function (error) {
console.log("Failed sending request!");
return Promise.reject(error);
});
window.axios.interceptors.response.use(function (response) {
console.log("Got headers:", response.headers);
if (response.headers.hasOwnProperty('authorization')) {
console.log("Got authorization:", response.headers.authorization);
Store.auth.setToken(response.headers.authorization);
}
return response;
}, function(err){
console.log("Got error", err);
});
I don't get any of the console.log's on page load.
I am setting my interceptors in the root app's beforeMount method. I've tried moving them to beforeCreate and I still get the same issue.
try this
window.axios.interceptors.request.use(function (config) {
console.log("Sent request!");
if(localStorage.getItem('id_token')!=undefined){
config.headers['Authorization'] = 'Bearer '+localStorage.getItem('id_token')
}
return config;} , function (error) {
console.log("Failed sending request!");
return Promise.reject(error); });

Angular2 post request despite a XMLHttRequest error

I send a request to a remote API. It takes a little time for API to proceed on its side.
After this little waiting time, i can see in network tab a HTTP 200. In the response, I got the proper intended information. Everything on the API side works fine.
BIT on the console, I can see I encountered a XMLHttpRequest Error.
Why, especially if I have a XMLHttpRequest Error, the POST is completed with 200? Shouldn't it be "blocked" by Angular2?
The unintended result is: my file is correctly uploaded and handled by the API, but in Angular2, it triggers the ERROR part of my call.
If I use https://resttesttest.com/ for example, it seems to encounter the same error but it doesn't finalize the POST:
Oh no! Javascript returned an
HTTP 0 error. One common reason this might happen is that you
requested a cross-domain resource from a server that did not include
the appropriate CORS headers in the response.
Angular 2 Code for this call
this.http
.post(this.documentUploadAPIUrl, formData, options)
.subscribe(
res => {
this.responseData = res.json();
console.log(this.responseData);
console.log('Uploaded a blob or file!');
},
error => {
console.log('Upload failed! Error:', error);
}
);
try to set withCredential attribute of xmlHttpRequest to true, this will send credentials managed by the browser, in angular 2 you can do like this
import { RequestOptions } from '#angular/http';
this.http
.post(this.documentUploadAPIUrl, formData, this.post_options)
.subscribe(
res => {
this.responseData = res.json();
console.log(this.responseData);
console.log('Uploaded a blob or file!');
},
error => {
console.log('Upload failed! Error:', error);
}
);
post_options() {
return new RequestOptions({ method: 'post', withCredentials : true });
}

Getting global handler to all AJAX calls in dojo

I need to invoke some common methods before an AJAX call is made and after the AJAX call (before the actual handler method is called) is success. I'm using dojo.aspect to achieve this.
This is my code sample
function makeAjaxCall(){
dojo.xhrGet({
url:"sample_url",
content:{
test:"value"
},
load:function(response){
//Do some logic here
},
error:function(response){
//handle error
}
});
}
Below is the dojo.aspect which I'm using to get a hook to the XHR calls.
define(["dojo/aspect"], function(aspect){
aspect.after(dojo, "xhr", function(deferred){
console.log("AJAX AFTER");
deferred.then(function(response){
//CALLED AFTER 'load' METHOD IS CALLED.
console.log("Testing");
});
});
aspect.before(dojo, "xhr", function(method, args){
console.log("AJAX BEFORE");
});
});
Now the problem is deferred.then inside aspect.after is called after the "load" function is called. Is it possible to have a method which is called before the actual load method is invoked?
The short answer is yes.
First, there are two ways to make ajax calls in Dojo.
dojo/xhr - this is what you have above and this is deprecated
in favor of
dojo/request/xhr
The first implementation will call into the second implementation. So I would recommend using aop on dojo/request/xhr.
aspect.around(require.modules['dojo/request/xhr'], 'result', function(originalXhr){
return function(url, options, returnDeferred){
var dfd = new Deferred();
// Logic before making the xhr call
originalXhr(url, options, returnDeferred)
.then(function(response) {
// Logic handling the response but before resolving the deferred.
dfd.resolve(vm);
// Logic after resolving the deferred.
}, function(err){
// error handling?
dfd.reject(msgs);
}, function(update) {
dfd.progress(update);
});
return dfd;
};
});
You can find the complete implementation at
https://github.com/cswing/evinceframework/blob/master/evf-web-js/src/dojo/evf/serviceRegistry.js (~ line 111)
USAGE:
require('dojo/xhr/request', function(xhr){
xhr({...}).then(
function(response) {
//handle response
},
function(error) {
//handle error
}
);
});
The dojo/xhr code will translate itself to the usage above, so the code you posted should work.
If you switch to the new API - dojo/request
Then you could use dojo/request/xhr and dojo/request/notify
In Dojo 1.10 there is new API to globally catch state of requests.
notify("error", function(error){
console.error(error);
//SyntaxError: Unexpected token < in JSON at position 0(…)
});
But in my case I get errors in html eg. so in error I get "error SyntaxError: Unexpected token < in JSON at position 0(…)"
In previous version there was an access to response object:
topic.subscribe("/dojo/io/error", function(/*dojo.Deferred*/ dfd, /*Object*/ response){
if (response.status === 401) {
window.location.reload();
}
});
So I figured out that json handler can be customized:
require(["dojo/request/handlers"], function(handlers){
handlers.register("json", function(response){
if (response.status === 401) {
window.location.reload();
return;
}
return JSON.parse(response.text || null);
});
});
This way you are able to detect response.errors before JSON.parse throws exception.

Resources