Loading controller await problem with Ionic - ionic-framework

In my ngOnInit page I call a function to present a Loading and then call my service to load data.
The problem is that the service call ends before the loading starts.
How is it possibile with await?
loading: any;
...
ngOnInit() {
this.presentLoading();
this.myService.get().subscribe((item)=>{
console.log('dismiss');
this.loading.dismiss();
}, ()=>{
this.loading.dismiss();
})
}
async presentLoading() {
this.loading = await this.loadingController.create({
message: 'Loading...',
duration: 20000
});
console.log('presentLoading')
await this.loading.present();
}
In console i can see:
dismiss
ERROR TypeError: Cannot read property 'dismiss' of undefined....
presentLoading
I’m using Ionic4.

In your case (based on the code) you have presentLoading function that returns a promise (async), so even though inside of it you are using await statements - inside the ngOnInit hook nothing instructs execution to await for the presentLoading.
You could do:
async ngOnInit() {
await this.presentLoading();
this.myService.get().subscribe((item)=>{
console.log('dismiss');
this.loading.dismiss();
}, ()=>{
this.loading.dismiss();
})
}
Also since you are using Onservables it may makes sense to call dismiss inside "completed" function:
async ngOnInit() {
await this.presentLoading();
this.myService.get().subscribe((item)=>{
console.log('dismiss');
}, (error)=>{
console.log(error);
}, (completed)=>{
this.loading.dismiss();
}
})
A note - making ngOnInit an async method does not "hurt", but its best to know a bit more waht implications it has: async/await in Angular `ngOnInit`

Related

Flutter workManager callbackDispatcher starts but do not finish the exrcution of a asynk function

Flutter workManager callbackDispatcher starts and calls the below function. But never finish it.
static Future<List<Map<String, dynamic>>> getItems() async {
debugPrint("In getItems");
final db = await DatabaseHelper.db();
final a = db.query('items', orderBy: "id");
debugPrint("post query, before return");
return a;
}
If I call the function onPressed it works fine.
If I call the same function from callbackDispatcher it Start and print "In getItems" but not print "post query, before return".
Getting no error message either.
I have registered it as one off task.
Workmanager().registerOneOffTask("task-identifier", "simpleTask");
Future<void> callbackDispatcher() async {
var sm= SmsSender();
Workmanager().executeTask((task, inputData) {
try {
sm.getAlertBookings();
smsCompleter.complete();
} catch(err) {
print(err.toString());
throw Exception(err);
}
return Future.value(true);
});
await smsCompleter.future;
}
What is causing this issue and how can I fix it?
I tested the same function onPressed it worked fine. callbackDispatcher Start the function but do not finish it.

async function returns Promise { <pending> }

I am trying to write a function that takes a URL and returns the engagement stats from Facebook Graph API against that URL. But I am facing trouble as my function is just giving me Promise { <pending> } as output.
Here is my code:
const getFacebookStats = async (link, ACCESS_TOKEN) => {
try {
const resp = await axios.get(
`https://graph.facebook.com/v12.0/?id=${link}&fields=engagement&access_token=${ACCESS_TOKEN}`
);
return resp;
} catch (err) {
// Handle Error Here
console.error(err);
}
};
Any help would be much appreciated.
Call your function like this:
getFacebookStats(link, ACCESS_TOKEN).then(response => {
console.log(response);
}).catch(error => {
console.error(error);
});
Or you could call it using await inside an async function.
Check this answer for a more detailed explaination of Promises in javascript.

How to conditionally click an element in Protractor?

In a protractor test, I need to close a pop-up if it appears (it doesn't always) and proceed with the test as normal. Here's the code I've got to do so-
let checkForPopUp = async function() {
element(by.css('button[id="gdprStopEmails"]')).isPresent().then(function (isVisible) {
return isVisible;
});
}
it('description', async function() {
let hasPopUp = await checkForPopUp();
if(hasPopUp) {
await element(by.id("gdprStopEmails")).click();
}
await connectedAccounts.revokePermission(partnerInfo.revokeId, partnerInfo.confirmRevokeId);
});
I ran this test a few times without checking if the element was there, and it closed the popup every time it was there (and failed the test when it wasn't). It hasn't closed the popup a single time since I introduced the condition check, and despite my best efforts I can't figure out what's up. Does anything jump out to you guys? Thanks in advance!
you're missing return. Your function returns nothing explicitly and thus implicitly returns undefined which is always falsy, and your if block doesn't get executed
This should work
let checkForPopUp = async function() {
return element(by.css('button[id="gdprStopEmails"]')).isPresent().then(function (isVisible) {
return isVisible;
});
}
it('description', async function() {
let hasPopUp = await checkForPopUp();
if(hasPopUp) {
await element(by.id("gdprStopEmails")).click();
}
await connectedAccounts.revokePermission(partnerInfo.revokeId, partnerInfo.confirmRevokeId);
});
but since you're using async/await don't mix syntaxes. I'd do it this way
let checkForPopUp = async function() {
return element(by.css('button[id="gdprStopEmails"]')).isPresent()
}
it('description', async function() {
let hasPopUp = await checkForPopUp();
if(hasPopUp) {
await element(by.id("gdprStopEmails")).click();
}
await connectedAccounts.revokePermission(partnerInfo.revokeId, partnerInfo.confirmRevokeId);
});
and keep in mind isPresent doesn't guarantee the visibility

Ionic 4 Loadingcontroller overlay doesnt exist

I created a simple function of creating a loading like this
async presentLoading() {
const loading = await this.loadingController.create({
message: 'Please Wait...',
});
await loading.present();
}
And i am closing the loader when the data is fetch like this
getUserData(){
console.log(this.userID);
this.api.getCompanyEmploye(this.userID).subscribe(res => {
this.loadingController.dismiss(); //closing here
console.log(res);
this.user = res.records[0];
this.familyMembers = res.records[0].family_members;
});
}
I am calling both function in constructor
constructor(public loadingController: LoadingController){
this.presentLoading();
this.getUserData();
}
Its showing error of ERROR Error: Uncaught (in promise): overlay does not exist
The issue is that your API call responds sooner than the loading controller gets instantiated. Instead of parallel calls, you should try to serialize those this way:
Make your presentLoading method to return Promise:
async presentLoading() {
const loading = await this.loadingController.create({
message: 'Please Wait...',
});
return loading.present();
}
Now you can call it this way:
getUserData(){
this.presentLoading().then(()=>{
this.api.getCompanyEmploye(this.userID).subscribe(res => {
this.loadingController.dismiss(); //closing here
console.log(res);
this.user = res.records[0];
this.familyMembers = res.records[0].family_members;
});
})
}
And in your constructor you need only to call for the API
for me, the issue is simply because I don't have .catch() for the promise. As#Sergey suggested, this is because the loader is not ready when you calling the ionic loader
this.loadingController.dismiss()
.then(async () => {
await this.setStorageForLocalData(data);
})
.catch(console.error);
where .catch() will dismiss the error

Ionic4 or 3 LoadingController (progress dialog)

I am using ionic4 LoadingController in the app. it is dismissed after a given interval of time, but don't want like that. I don't want to set the time. before calling web api i will display LoadingController and I want to dismiss it whenever I will get the response from rest service. can anyone help me how to implement it?
You should do something like this:
async function presentLoading() {
const loader= document.querySelector('ion-loading-controller');
await loader.componentOnReady();
const element = await loader.create({
message: 'Please wait...',
spinner: 'crescent',
duration: 2000
});
return await element .present();
}
// Initialize variable
private loader: any;
private loaderActive: boolean = false;
// Generic method to display the loader
async showLoader() {
this.loaderActive = true;
this.loader = await this.loadingCtrl.create({
message: 'Please wait...',
spinner: 'crescent',
});
await this.loader.present();
}
// Generic method to dismiss the loader
async dismissLoader() {
if (this.loaderActive === true) {
await this.loader.dismiss();
}
this.loaderActive = false;
}
Before api call just call the method this.showLoader(), once you get the response
just call the this.dismissLoader() method.
I would take a guess and say that you are using HttpClient to get your data from your rest service, therefore I would propose this scenario for you,
First of all we start by displaying the loader:
let loader = await this.loadingCtrl.create({
//Your loader content and options
});
loader.present();//show the loader
After that we get the data using the HttpClient. let suppose that we injected that's way public http: HttpClient so it depends on your rest service http mthod (post, get, put ...). the code would be:
this.http.get("url").subscribe((data: any) => {
//process your data here
loader.dismiss();//then we hide the loader
});
Leave me a comment if I misunderstood it.