Friends,
I am using web service and forms for a number of situations in my project. But now when I try to use same strategy the data is not provided by the provider function. It gives ‘null’ value always. But I can see the value in chrome web console.
My provider function is
getYearMaster()
{
var obj = {wsname: 'YearMaster' };
var myData = JSON.stringify(obj);
if(this.data)
{
return Promise.resolve(this.data);
} else {
return new Promise
(
resolve =>
{
this.http.post('http://apps.windows.gov.in/mobservice/index.php/xxx/',myData,{ headers: new HttpHeaders()
, responseType: 'json'})
.map(res => res)
.subscribe
(res => {
resolve(res);
},
err => {console.log("oops some error in Project Financial year selection");}
);
}
);
}
}
the calling controller is
getYearMaster()
{
let loader = this.loadingController.create({
content: "Loading Financial Year ... "
});
loader.present();
if(this.global1.getnetwork())
{
this.connectivityFlag = true;
this.projectplanprovider.getYearMaster()
.then(data => {
this.searchFlag = true;
this.result = data;
alert("data in fun is:"+data); // data in fun is 'null'
this.year = data;
loader.dismiss();
}, error => {
alert("error recieved : " + error ); //it will not happen any time
loader.dismiss();
});
} else {
this.presentAlert();
}
}
What may be the problem ? I could not find any error . Please advise
@anespa Try to put some logs to see what is happening in the provider:
public getYearMaster() {
const obj = {wsname: 'YearMaster' };
const myData = JSON.stringify(obj);
if (this.data) {
console.log('already has the data', this.data);
return Promise.resolve(this.data);
} else {
return new Promise(resolve => {
console.log('will call the web service');
const url = 'http://apps.windows.gov.in/mobservice/index.php/xxx/';
this.http.post(url, myData, { headers: new HttpHeaders(), responseType: 'json'}).map(res => {
console.log('res1', res);
return res; // is this map needed, when it is returning the same value?
}).subscribe(
res => {
console.log('res2', res);
resolve(res);
},
err => {
console.log('oops some error in Project Financial year selection');
}
);
});
}
}
See if the logs are correct:
will call the web service res1 [value] res2 [value]
Or if this.data is defined:
already has the data [value]
Check if the value is correct, and where it is returned.
Hey man I just wanted to say that you are leveraging promise and an observable inside of it…I am not sure what makes your use case (to retrieve data from a service) so unique that you are using this pattern?
Highly advise you to use simple approaches:
create methods that return observables for your API calls
call to subscribe to those methods from your components
Try to use the patterns advised at angular.io as much as you can to avid these snowflakes.
Actually my problem is the code works and it go fast without getting a value from server . I need a solution which work like await/async. Please advise in current code how it can implement ?
This is a typical error found when we work with Angular and Ionic, the problem appears because when your app loaded in a browser on your app loads all the content from an origin that comes from your local address http://localhost:8100, then when you want to make any AJAX request sent out to another host than localhost:8100 the request is called from an any point different from the origin its require a CORS(Cross Origin Resource Sharing) preflight request to see if it can access the resource.
Based on your logs (res1 null) I think you are not receiving the value from the backend. I don’t think it’s a CORS issue or some backend error response, otherwise (I think) you would receive an error in the http request.
Can you log in your backend to see if your webservice is being called? Seeing the url I think it’s not your backend (you call a third party service). Can you see in the network tab of the developer tools (or in the console) if the method is returning an error?
Are you sure that method is a POST? A method where you getYears() seems more like a GET (this.http.get(...)). Can you call the service (using the url directly, or with Postman or some such service) without ionic and see if it returns correctly?
@anespa In your code you have http://apps.windows.gov.in/mobservice/index.php/xxx/. It’s not the same url than the one in your screenshot.
First see if
The url you are calling is the right one.
If the http method is correct (GET, POST, …)
If the response status code is correct (200, 2XX)
If the response body is what you want (the json content)
Can you tell me if all these steps are successful?
Also, you should be able to call it using Postman. If you can’t, you should try to solve that first (perhaps the problem is exactly that, and if you discover the problem using Postman the same problem will be solved in Ionic).
The solution to this problem (I talked with @anespa in a private message and found the solution), in case it happens with someone else, is the following:
When using responseType: 'text' (instead of 'json'), it returned the value from the server as a plain string (with responseType: 'json' it returned null). If I tried to parse the string I received an error tough.
The response body from the server was returning a JSON, but the 1st character was invalid (charcode 65279). You can’t see this character, though, so if you logged the response as a string you wouldn’t see it, but if you tried to call JSON.parse() it was given an error (Uncaught SyntaxError: Unexpected token with JSON.parse).
The angular HttpClient probably tries to parse the string when the responseType is json, but, if it can’t, it swallows the exception (I assume) and returns null, making it harder to discover the error.
The solution to this was making a substring with the original string from the 1st valid character onwards (it could be made in other ways):
this.http.post(url, JSON.stringify(obj), { responseType: 'text' }).subscribe(
body => {
body = body && body.substring(body.indexOf('[')); // because I know the response is an array
const obj = body ? JSON.parse(body) : null;
resolve(obj);
},
err => {
console.log('oops some error in Project Financial year selection');
}
);