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.
Related
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
I am able to implement voice and video call using agora.io library which is available at https://www.agora.io/ && https://github.com/AgoraIO/Flutter-SDK
how ever the process for starting a call is both user has to join a particular channel name defined by the user manually or automatically. which is not the practical way.
Is there any way to create a separate signalling system (may be using, nodejs socket, firebase or one-signal notification? )
What's the simultaneous/parallel way to be used along side that?
or what's the complete alternative?
Agora.io doesn't provide any method other passing a channel name manually or a default string. But what you can do is use Firebase dynamic link to share the channel name via a dynamic link. This link will redirect you to the page where you're taking channel name as input and fill the channel name according to the parameters passed. So your code will look something like:
class AgoraImpementation extends State<AgoraImplementation> {
#override
void initState() {
super.initState();
this.initDynamicLinks();
}
initDynamicLinks(BuildContext context) async {
await Future.delayed(Duration(seconds: 3));
var data = await FirebaseDynamicLinks.instance.getInitialLink();
var deepLink = data?.link;
final queryParams = deepLink.queryParameters;
if (queryParams.length > 0) {
var channelName = queryParams['channel_name'];
openFormScreen(channelName);
}
FirebaseDynamicLinks.instance.onLink(onSuccess: (dynamicLink)
async {
var deepLink = dynamicLink?.link;
final queryParams = deepLink.queryParameters;
if (queryParams.length > 0) {
var userName = queryParams['channel_name'];
openFormScreen(channelName);
}
debugPrint('DynamicLinks onLink $deepLink');
}, onError: (e) async {
debugPrint('DynamicLinks onError $e');
});
}
openFormScreen(String userName){
Navigator.of(context).pushNamed("routeFormScreen", arguments: {"channelName": channelName});
}
}
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
getData() async {
http.Response response = await http.get('https://www.example.com/);
print(response.body);
}
The above function works to get the HTML code of a page but it fails in some cases. The function is sometimes never completed and it waits forever to get response( For example, if the app is opened while internet is off and even when its turned on, it never connects). In such situations is there any way to retry ?
I tried the http retry package but it gives me 15+ errors.
Example code for how this could be done:
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<List> loadData() async {
bool loadRemoteDatatSucceed = false;
var data;
try {
http.Response response = await http.post("https://www.example.com",
body: <String, String>{"username": "test"});
data = json.decode(response.body);
if (data.containsKey("success")) {
loadRemoteDatatSucceed = true;
}
} catch (e) {
if (loadRemoteDatatSucceed == false) retryFuture(loadData, 2000);
}
return data;
}
retryFuture(future, delay) {
Future.delayed(Duration(milliseconds: delay), () {
future();
});
}
You can use RetryPolicy from http package to retry your connection, just create your own class and inherit form RetryPolicy and override these function like the following example, then create a Client using HttpClientWithInterceptor.build and add your custom retryPolicy as a parameter, this will retry your request for a number of times until a condition is met, if not, it'll just stop retrying.
import 'package:http/http.dart';
class MyRetryPolicy extends RetryPolicy {
final url = 'https://www.example.com/';
#override
// how many times you want to retry your request.
int maxRetryAttempts = 5;
#override
Future<bool> shouldAttemptRetryOnResponse(ResponseData response) async {
//You can check if you got your response after certain timeout,
//or if you want to retry your request based on the status code,
//usually this is used for refreshing your expired token but you can check for what ever you want
//your should write a condition here so it won't execute this code on every request
//for example if(response == null)
// a very basic solution is that you can check
// for internet connection, for example
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
return false;
} on SocketException catch (_) {
return false;
}
}
}
then create and use a client to make your requests.
it will automatically retry the request if the condition you wrote is met.
Client client = HttpClientWithInterceptor.build(
retryPolicy: ExpiredTokenRetryPolicy(),
);
final response = await client.get('https://www.example.com/);
there is also a package to check for internet connection if that your problem, see connectivity
You can use try-catch blocks inside async functions like you would in synchronous code. Perhaps you'd be able to add some sort of error handling mechanism in the function, and retry the function on error? Here's some documentation on that one.
Example from the docs:
try {
var order = await getUserOrder();
print('Awaiting user order...');
} catch (err) {
print('Caught error: $err');
}
You can also catch specific Exceptions, per this github issue.
doLogin(String username, String password) async {
try {
var user = await api.login(username, password);
_view.onLoginSuccess(user);
} on Exception catch(error) {
_view.onLoginError(error.toString());
}
}
EDIT: This may also help.
While we're at it, look here for a function that reattempts an async operation however many times you need.
I am using Ionic 4 and the Loading Controller.
async presentLoading() {
const loading = await this.loadingCtrl.create({
message: 'wait. . .'
});
return await loading.present();
}
Works great. But now I want to dismiss the loader programatically.
this.loadingCtrl.dismiss().then(a => console.log('dismissed'));
Even though I see 'dismissed' on my console (logging worked) the loading overlay continues. Any idea what might be the reason?
You not dismissing the actual loader that is displayed. You have to dismiss it with loading variable like below :
loading.dismiss().then(a => console.log('dismissed'));
Notice that I have used variable loading that you have declared for current loader.
If you want to dismiss programmatically use this in your service.
export class LoaderService {
private isLoading = false;
constructor(private loadingController: LoadingController) {
}
async presentLoading() {
// issue generated! so we used Boolean value to set loader dismissed call
firstly so we used this logic
this.isLoading = true;
let loading = await this.loadingController.create({
message: 'Please Wait',
spinner: 'bubbles'
}).then((res) => {
res.present();
if (!this.isLoading) {
// res.dismiss().then(()=> console.log('abort presenting'));
this.loadingController.dismiss().then(() =>
console.log('Dismissed'));
}
});
return loading;
}
async hideLoading() {
this.isLoading = false;
return await this.loadingController.dismiss().then(() => console.log('Dismissed'));
}
}