I have a method in service to get httprequest from another server and in the components console get null of value ollayer but data is not null
ollayer={};
service:
getLayer(): Observable<any> {
return this.http.get<olLayer>(
'http://localhost:3000/geomap/getlayer',
);
}
components:
this.olservice.getLayer().subscribe((data) => {
this.ollayer = data;
console.log(data)
});
console.log(this.ollayer)
That behaviour is fine, that's how asynchronous pipelines work.
For whatever reason you need the data, for example, to update a view on your web page, you have to do it in the subscribe scope. For example, you are updating this.ollayer inside the subscribe, so any view properly binded to that variable will update when the request is done.
Edit: it is ok for data being null on your second log because data may not have arrived yet. But it is not ok to be null on the log inside the subscribe.
Related
I have a service that returns me the user's data according to the Token stored in the localStorage and everything is returned correctly until I get to my component.
The real problem is that I have the following code in my component.ts file:
Apparently, at least everything should work out for me. However, in the console it is possible to notice that even after I have assigned the return to my user property it is printed as undefined. As shown in the image below.
When trying to use in the HTML template I get messages saying that it was not possible to load data from the user property. I have already tried using async pipe like this: (user $ | async) as user. I tried to use the safe navigation like this:user?.email.
But it did nothing and I have no idea why this happens. Any help will be welcome!
User$ represents a stream, should be assigned this way:
export class {
// a stream type
user$: Obserable<User>;
ngOnInit() {
// a stream type
this.user$ = this.clienteHeaderService.getUser();
}
}
and the template add |async pipe.
this.user is not immediately available after you call subscribe(), it is very possible that the getUser() hasn't emitted any result by the time console.log(this.user) is called.
If you just wanted to see what's in this.user, you may try it in the callback of subscribe()
this.clientHeaderService.getUser().subscribe((response) => {
this.user = response;
console.log(this.user); // this.user should be available here
})
On the template side, you should be able to just access the user via {{ user }}.
I'd also suggest to use share your minimum reproducible code at https://stackblitz.com/, to get help more easily.
Subscribe almost work like promise in javascript and it has a callback
.subscribe(response=>this.user=response)
Callback are pushed to the end of current event loop .So you are accessing
console.log(this.user)
before callback in your subscribe get executed.
instead
try
.subscribe((response) => {
this.user=response;
//you can access value of this.user here or call other function here to
//access this.user
console.log(this.user);
})
I'm trying to get the data from my Firebase with AngularFire2.
I want to check specific data and after I get this data from Firebase, I can check it only in the specific scope and not after the operation to Firebase. Why does it happen?
Below is my code:
this.af.database.list('/users/1qfcMAQnglX9jsW5GdLpPko1HqE2', { preserveSnapshot: true})
.subscribe(snapshots=>{
snapshots.forEach(snapshot => {
if(snapshot.key=="reg_boolean"){
console.log(snapshot.val());
this.bo=snapshot.val();
}
this.currentUser.push({key:snapshot.key,value:snapshot.val()});
console.log(this.currentUser);
//console.log(snapshot.key, snapshot.val());
if(this.bo==true){console.log("happy"); }; //i can access only in this scope
});
})
if(this.bo==true){console.log("happy"); }; //why i can access this value??it's undefined, this happen before the subscribe with angularfire2
It's undefined because this.af.database.list it's asynchronous so the code in subscribe will execute when this.af.database.list does retrieve the data. So when the code got to the line if(this.bo==true){console.log("happy"); }; It has nothing because subscribe did not finish at all.
The subscribe it's like the old promise but now it's working with rxjs I recommend you to learn it because angular and ionic has a lot of focus on that.
Try looking at https://www.learnrxjs.io/
I'm running into a bit of a problem with an Angular (1.4) service. The code is roughly as follows :
service.retrieveStuffFromServer = function() {
return httpCallFromServer().then(
function(data) {
if (Array.isArray(data)) {
return data;
}
return [];
}
);
};
I call this function in two distinct controllers. Most of the times, it works as intended, but I'm having problem in those conditions :
The HTTP call takes time to return the data
Controller A calls the service.
Controller B calls the service.
The service returns data to controller A
The call in the controller B is cancelled. The logic after it never executes
My first guess would be to slightly alter the service, to inform either of the controllers if the service is already busy so I can retry later, but I'm not sure if this is the best solution, so I'm looking for some advice.
Hard to say why it doesn't just work, but presumably something in httpCall() is preventing the same call from being made again before the 1st one completes, and it rejects if that happens. But if you want controller B call to share the response from an active previous call, you could cache the promise:
function myFunction() {
if (!myFunction.promise) {
myFunction.promise = httpCall()
.then(function(result) {
myFunction.promise = undefined;
return ...
}, function(err) {
myFunction.promise = undefined;
throw err;
});
}
return myFunction.promise;
}
This will cause the same promise from a prior call to be returned as long as the prior call is still unresolved.
Using a property of the function itself as a cache is a convenient way to keep state associated logically with the function itself. You could just use any variable defined outside the scope of myFunction though.
I've got an AngularJS resource implementation, which (in principle) works fine. Now the special circumstances are:
one of the fields (attributes) of the resource is the "last changed timestamp"
if it arrives at the server in an updating request, it is ignored. The sever sets the "last changed timestamp" always automatically
the updating methods on the server are all implemented in a way, that the response is empty (rather than containing the modified entity)
So under these circumstances, to get the "last changed timestamp" after an update operation from the server, I always have to do a get immediately following the update.
myEntity.$update( function(){ myEntity.$get(); } );
Now the question is: Does AngularJS offer a way to automatically chain actions:
to define in the MyEntity definition, that it needs to always do a $get after the $update.
and then, in application code just call
myEntitty.$update();
Thanks to #marck for pushing me in the right direction. The solution is basically
var MyEntity = $resource( ...,
{
get: {...},
update: {...}
}
);
// params is passed to $update.
// after successful $update, a parameterless $get is called
// success is called after successful $get
// error is called if $update OR $get failed
// returns the promise of the $update
MyEntity.prototype.$updateAndRefresh = function(params, success, error){
var item = this;
return item.$update(params, function(){
item.$get(success, error);
},
error);
}
I am trying to get data from json data so i write this:
app.factory('data', function($resource) {
return $resource('mock/plane_urls.json', {}, {
getTreeData: { method: 'GET', isArray: false }
})
})
and then using:
data.getTreeData.Carriers.Carrier;
Where Carriers is the first node in json file. but it doesnt work ;/ I got error
Error: data.getTreeData.Carriers is undefined
You are trying to reach into the Carriers object before it is fetched. Before the data comes back, Carriers is just an empty object.
You could do something like $scope.carriers = data.getTreeData(); and then in your view have an element with ng-repeat="carrier in carriers"
The idea behind $resource is that you get an empty object, so the view renders nothing. When the request is complete, the empty object is replaced and the view is re-rendered with the data automatically.
You could also use the $http service like so and provide a callback function that executes once the data is fetched.
$http.get('mock/plane_urls.json').then(function(data){
carrier = data.Carriers.Carrier
});
BUT! should break this into a service and a controller though. Just have the service getTreeData return the promise object like so: return $http.get('mock/plane_urls.json'); and then in your controller call it with then() and provide the callbacks for success and error:
getTreeData.then(
function(data){
carrier = data.Carriers.Carrier;
},
function(err){
console.log("Error: " + err);
});
You can use $scope.$watch to watch the value of the data.getTreeData.
When new data comes in, the callback will be called, then, you can get your data you want.
http://docs.angularjs.org/api/ng.$rootScope.Scope