As said in the title, nothing is happening when I subscribe to my observable. There is no error in the console or during the build. Here is my code :
My service
getBlueCollars(): Observable<BlueCollar[]> {
return this.http.get(this.defaultAPIURL + 'bluecollar?limit=25').map(
(res: Response) => {
return res.json();
});
}
My component
ngOnInit() {
this.planifRequestService.getBlueCollars().subscribe(
data => {
this.blueCollars = data;
console.log('Inner Blue Collars', this.blueCollars);
},
err => console.log(err)
);
console.log('Value BlueCollars : ', this.blueCollars);
}
So the second console.log is triggering with "Value BlueCollars : Undefined", and the log in my subscribe is never showed. As well, I can't see the request sent in the Networt tab of Chrome.
So I tried to simplify everything with the following code :
let response: any;
this.http.get('myUrl').subscribe(data => response = data);
console.log('TestRep: ', response);
Same problem here, no error, response is undefined. It seems the subscribe is not triggering the observable. (The URL is correct, it is working on my swagger or with postman.)
I'm on Angular 2.4.9
Edit
So I tried to copy/past the code of my request on a brand new project, everything is working fine. The request is triggered and I can get the JSON response correctly. So there is something maybe on the configuration of my project that is forbiding the request to trigger correctly.
Ok just found what was going on. I am using a fake backend in order to try my login connexions that is supposed to catch only specified URL. However for wathever raison it was catching all the requests, so that explain everything. Thx for your help everybody.
Try adding a catch block to your service code:
getBlueCollars(): Observable<BlueCollar[]> {
return this.http.get(this.defaultAPIURL + 'bluecollar?limit=25')
.map(
(res: Response) => {
return res.json();
})
.catch(err => Observable.throw(err))
}
Don't forget to
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';`
I imagine this will result in the error that'll give you an idea where your code is going wrong.
The reason the console.log outside the subscribe call is undefined is because the subscribe/http call is happening asynchronously and so, in effect, the order (in time!) the code is running is:
1) the observable is subscribed to (and then waits for a response)
2) the outer console log runs with blueCollars undefined
3) when the response (or error) comes back from the http request (potentially after several seconds), only then will the inner assignment of this.blueCollar = data happen (and the inner console log), OR an error will get logged
Apart from that the subscribe code looks fine...!
Related
I have this function...
function waterCalibrator() {
axios.post("http://localhost:3001/api/update-water", {
waterValue: props.moisture
}).then(function(response){
console.log("Water calibration worked")
console.log(response);
}).catch(function(error) {
console.log(error);
})
props.airValueObject.setWaterFlag(true);
props.airValueObject.setWaterValue(props.moisture);
}
Can anyone explain why then() is not ever triggered? I have no errors. It simply isn't triggering. Everything works except for this...
}).then(function(response){
console.log("Water calibration worked")
console.log(response);
}).catch(function(error) {
console.log(error);
})
server side looks like this...
app.post("/api/update-water", (req, res) => {
const waterValue = req.body.waterValue;
const sqlUpdateWater = "UPDATE user SET waterValue=? WHERE uid='j' ";
db.query(sqlUpdateWater, [waterValue], (err, result)=>{
console.log(`water is: ${waterValue}`)
})
})
You are getting a 204 status code, which means the request went through successfully but there is no content at all, hence you are trying to log nothing.
The HTTP 204 No Content success status response code indicates that the request has succeeded, but... The common use case is to return 204 as a result of a PUT request, updating a resource, without changing the current content of the page displayed to the user. If the resource is created, 201 Created is returned instead. If the page should be changed to the newly updated page, the 200 should be used instead.
You also need, as suggested in previous comments, open the dev console and check the status of the promise itself. This promise seems to be successful.
If this answer helps solving the issue, consider accepting the answer or upvoting it. Thanks.
I'm trying to log an error from a subscribe, but the error seems... incomplete?
I've never seen this kind of problem, nor could I find anything on Google. The code is the following:
this._http.post(this.urlPath, email).subscribe(
res => {
// stuff
},
err => {
console.log(err) // <- I need to log this
}
);
It works to an extent. When I open the browser's console, in order to check the error, what I get is this:
The thing is, it seems like there's missing information here. If I open the Network tab, the response for this same request looks like this:
As you can see, the real response has more information. I've tried using {observe: "response"}, but to no avail. I should note that if I try using fetch, the response comes complete, but I'd rather use HttpClient.
What is going on here?
When you receive a http error status code you can't access to the payload returned by the service by the same way that in a success case. Is like an special object.
But you can acccess to it doing some like this, using a pipe in your service and an error handler. This is a minimal example of it:
your.service.ts
...
handleError(error) {
return throwError(error.error);
}
return this.http.get ... the rest of your request.pipe(
catchError(this.handleError)
);
...
And where you consume your service, in err you can acces to full response that your error request contains.
...
, error => {
console.warn(error);
}
Or better than, you can throw the entire object to access to the error (response body) and the rest of params, like status code.
I am trying to speed up the network critical path on a website, and find out about the great <link rel=preload. So I try to anticipate the call that my single page application do as soon as the JS kicks in, I have put in my index.html
<link rel="preload" href="/api/searchItems" as="fetch" />
Then as the JS starts I make the same call with the help of the axios library:
await axios.get(`/api/searchItems`, { params: queryParams });
I would expect to see the call of Axios returning instantly the preloaded JSON file but instead, I see this:
As you can see the same call is loaded twice.
What I am doing wrong?
EDIT: I have added cache-control: public and nothing changes.
EDIT2: I also tried this code instead of axios:
let data = await fetch('/api/searchItems')
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error('HTTP error ' + response.status);
})
.catch(() => {
data = null; // Just clear it and if it errors again when
// you make the call later, handle it then
});
And nothing change
Three options for you:
It looks like your response has headers making it uncacheable for some reason. You may be able to fix it so it's cacheable.
Use a service worker.
Another approach, if this is really critical path, is to have some inline JavaScript that actually does the call and modify the code that will do the call later to look to see if the previous result is available, like this:
let firstLoad = fetch("/api/searchItems")
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error("HTTP error " + response.status);
})
.catch(() => {
firstLoad = null; // Just clear it and if it errors again when
// you make the call later, handle it then
});
(I'm using fetch there because you may want to do it before you've loaded axios.)
Then in the code that wants this data:
(firstLoad || axios.get("/api/searchItems").then(response => response.data))
.then(/*...*/)
.catch(/*...*/);
firstLoad = null;
If the content requires revalidation (and you're using no-cache, so it does¹), #2 and #3 have the advantage of not requiring a second request to the server.
¹ From MDN:
no-cache
The response may be stored by any cache, even if the response is normally non-cacheable. However, the stored response MUST always go through validation with the origin server first before using it...
(my emphasis)
In my Vue app, I instantiate a single instance of axios and use it across the app for HTTP requests. I have set up a response interceptor which checks if any response from the backend is 401 unauthorized, and if so, shows an alert message. This basic flow has been implemented, but you need to hit "OK" on the alert message twice for it to go away, and I am not sure why.
Axios instance:
import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
const axiosInstance: AxiosInstance = axios.create();
axiosInstance.interceptors.response.use(
(response: AxiosResponse) => response,
(error: AxiosError) => {
if(error.response && error.response.status === 401) {
alert('There has been an issue. Please log out and then log in again.');
return Promise.reject(error);
}
}
);
export default axiosInstance;
The request whose response is being intercepted:
import axiosInstance from 'axios-instance';
public async getloggedInUserId() {
await axiosInstance.get('/sessions.json')
.then((response) => {
if(response.data.user_id) {
this.SET_USER_ID(response.data.user_id);
}
});
}
I've read this thread, but my issue seems to be different: Javascript alert shows up twice
I've tried changing the return statement from return Promise.reject(error); to return false; but that did nothing for me.
As Phil suggested in the comment above, looking at at the Network tab in the browser console helped me solve the issue. The console showed how each component in the page was being loaded along with the resulting response code. In short, two processes were actually returning 401, which was the reason why the alert was being called twice.
I have decided to move the code that calls alert from a global axios interceptor (called whenever any process returns 401) to a .catch block inside one specific axios process, so that it only gets called once.
Your promise throws error in axios error interceptor, and error called second times.
I have a small component in vuejs for file uploading (using axios). I am trying to emit the response from the file upload like this:
methods: {
...
upload (){
axios.put(URL).then(response => {
console.log('response', response)
this.$emit('uploaded', response)
}).catch(error => {
})
}
}
But in this code, even though the console.log() response shows up fine, the emit shows undefined. I think the emit is getting called before the response is ready.
Is there anyway to use async/await to solve this issue?
console.log response shows up fine but the emit shows undefined.
Not sure what you mean by that, because if the response is available inside of console.log it should also be available inside of this.$emit. (Unless this.$emit itself is giving you undefined in which case you have scoping issues, but that shouldn't be the case as you seem to be using arrow functions).
I think the emit is getting called before the response is ready
It is inside of a callback so it should only get called once the request completes.
But if you want to try async / await then do this:
async upload() {
try {
let response = await axios.put(URL);
console.log('response', response)
this.$emit('uploaded', response)
} catch(error) {
// error
}
}