Dart cannot break out of loop while inside awaited then callback - flutter

I'm trying to generate random int and check if the integer is exists in Firebase database, and do this infinitly until the integer is not exist inside database.
Below my code:
while (true) {
_changeRandomInt()
firebaseFirestore.collection("myCollection").doc(_randomInt).get().then((DocumentSnapshot documentSnapshot) {
if (getFromFirebase(documentSnapshot) == null) {
break;
}
});
}
But I cannot even run this code. Error: A break statement can't be used outside of a loop or switch statement. Try removing the break statement. I have my break inside while loop, then why I'm getting this error? How to fix this?

A break statement can't be used outside of a loop or switch statement. Try removing the break statement.
This is self explanatory. You can't use break outside of a loop. Which in your case is inside a future.
Do something like this:
_changeRandomInt();
firebaseFirestore.collection("myCollection").doc(_randomInt).get()
.then((DocumentSnapshot documentSnapshot) {
while (getFromFirebase(documentSnapshot) != null){
//the body of this loop will only execute as long as the value isn't null
//will break out of the loop as soon as the value is null
}
}

The break you have used is inside then(), which means no loop is available immediately above `break. You can refactor your code in this manner to get it working.
while (true) {
_changeRandomInt()
final documentSnapshot = await firebaseFirestore.collection("myCollection").doc(_randomInt).get();
if (getFromFirebase(documentSnapshot) == null) {
break;
}
}
If getFromFirebase is also a future, then await that as well inside if block.

You want to do something like this:
void functionName() async {
try{
var ans;
while(getFromFirebae(ans)== null){
ans = await firebaseFirestore.collection("myCollection").doc(_randomInt).get();
}
} catch(e){
//error
}
}
However, this is not the correct way. A good practice is to create a loading widget, that would show an animation while the future is loading. An even better way - to load everything in the background without stalling the overall app.

Some people have been saying that you're using "break inside a Future", but that's not quite right. Your problem is that you're using break inside of a separate function body. This is equivalent to writing:
void f() {
break;
}
which doesn't make sense since break is not used directly within a local loop or switch statement. It doesn't matter that you're creating your function within a loop; break and continue statements perform local control flow (within a function), not across functions.
In general, instead of using Future.then, you should prefer using async/await which will have the compiler generate the callback function with appropriate code transformations for you:
while (true) {
_changeRandomInt()
var documentSnapshot =
await firebaseFirestore.collection("myCollection").doc(_randomInt).get();
if (getFromFirebase(documentSnapshot) == null) {
break;
}
}
Note that performing an asynchronous operation continuously in a loop isn't very efficient, so you probably should consider alternative approaches if possible, however.

Related

Flutter Future timeouts not always working correctly

Hey I need some help here for How to use timeouts in flutter correctly. First of all to explain what the main goal is:
I want to recive data from my Firebase RealTime Database but need to secure this request api call with an time out of 15 sec. So after 15 sec my timeout should throw an exception that will return to the Users frontend the alert for reasons of time out.
So I used the simple way to call timeouts on future functions:
This functions should only check if on some firebase node an ID is existing or not:
Inside this class where I have declared this functions I also have an instance which called : timeoutControl this is a class which contains a duration and some reasons for the exceptions.
Future<bool> isUserCheckedIn(String oid, String maybeCheckedInUserIdentifier, String onGateId) async {
try {
databaseReference = _firebaseDatabase.ref("Boarding").child(oid).child(onGateId);
final snapshot = await databaseReference.get().timeout(Duration(seconds: timeoutControl.durationForTimeOutInSec), onTimeout: () => timeoutControl.onEppTimeoutForTask());
if(snapshot.hasChild(maybeCheckedInUserIdentifier)) {
return true;
}
else {
return false;
}
}
catch (exception) {
return false;
}
}
The TimeOutClass where the instance timeoutControl comes from:
class CustomTimeouts {
int durationForTimeOutInSec = 15; // The seconds for how long to try until we throw an timeout exception
CustomTimeouts();
// TODO: Implement the exception reasons here later ...
onEppTimeoutForUpload() {
throw Exception("Some reason ...");
}
onEppTimeoutForTask() {
throw Exception("Some reason ...");
}
onEppTimeoutForDownload() {
throw Exception("Some reason ...");
}
}
So as you can see for example I tried to use this implementation above. This works fine ... sometimes I need to fight with un explain able things -_-. Let me try to introduce what in somecases are the problem:
Inside the frontend class make this call:
bool isUserCheckedIn = await service.isUserCheckedIn(placeIdentifier, userId, gateId);
Map<String, dynamic> data = {"gateIdActive" : isUserCheckedIn};
/*
The response here is an Custom transaction handler which contains an error or an returned param
etc. so this isn't relevant for you ...
*/
_gateService.updateGate(placeIdentifier, gateId, data).then((response) {
if(response.hasError()) {
setState(() {
EppDialog.showErrorToast(response.getErrorMessage()); // Shows an error message
isSendButtonDiabled = false; /*Reset buttons state*/
});
}
else {
// Create an gate process here ...
createGateEntrys(); // <-- If the closures update was successful we also handle some
// other data inside the RTDB for other reasons here ...
}
});
IMPORTANT to know for you guys is that I am gonna use the returned "boolean" value from this function call to update some other data which will be pushed and uploaded into another RTDB other node location for other reasons. And if this was also successful the application is going on to update some entrys also inside the RTDB -->createGateEntrys()<-- This function is called as the last one and is also marked as an async function and called with its closures context and no await statement.
The Data inside my Firebase RTDB:
"GateCheckIns" / "4mrithabdaofgnL39238nH" (The place identifier) / "NFdxcfadaies45a" (The Gate Identifier)/ "nHz2mhagadzadzgadHjoeua334" : 1 (as top of the key some users id who is checked in)
So on real devices this works always without any problems... But the case of an real device or simulator could not be the reason why I'am faceing with this problem now. Sometimes inside the Simulator this Function returns always false no matter if the currentUsers Identifier is inside the this child nodes or not. Therefore I realized the timeout is always called immediately so right after 1-2 sec because the exception was always one of these I was calling from my CustomTimeouts class and the function which throws the exception inside the .timeout(duration, onTimeout: () => ...) call. I couldn't figure it out because as I said on real devices I was not faceing with this problem.
Hope I was able to explain the problem it's a little bit complicated I know but for me is important that someone could explain me for what should I pay attention to if I am useing timeouts in this style etc.
( This is my first question here on StackOverFlow :) )

async/await - calling an async API from a syncronous method using dart [duplicate]

I'm on the way to evaluate Dart for a German company by porting various Java programs to Dart and compare and analyze the results. In the browser Dart wins hands down. For server software performance seemed to be a serious isssue (see this question of me) but that got mostly defused.
Now I'm in the area of porting some "simple" command-line tools where I did not expect any serious problems at all but there is at least one. Some of the tools do make HTTP requests to collect some data and the stand-alone Dart virtual machine only supports them in an asynchronous fashion. Looking through all I could find it does not seem to be possible to use any asynchronous call in a mostly synchronous software.
I understand that I could restructure the available synchronous software into an asynchronous one. But this would transform a well-designed piece of software into something less readable and more difficult to debug and maintain. For some software pieces this just does not make sense.
My question: Is there an (overlooked by me) way to embed an asynchronous call into a synchronously called method?
I imagine that it would not be to difficult to provide a system call, usable only from within the main thread, which just transfers the execution to the whole list of queued asynchronous function calls (without having to end the main thread first) and as soon as the last one got executed returns and continues the main thread.
Something which might look like this:
var synchFunction() {
var result;
asyncFunction().then(() { result = ...; });
resync(); // the system call to move to and wait out all async execution
return result;
}
Having such a method would simplify the lib APIs as well. Most "sync" calls could be removed because the re-synchronisation call would do the job. It seems to be such a logical idea that I still think it somehow exists and I have missed it. Or is there a serious reason why that would not work?
After thinking about the received answer from lm (see below) for two days I still do not understand why the encapsulation of an asynchronous Dart call into a synchronous one should not be possible. It is done in the "normal" synchronous programing world all the time. Usually you can wait for a resynchronization by either getting a "Done" from the asynchronous routine or if something fails continue after a timeout.
With that in mind my first proposal could be enhanced like that:
var synchFunction() {
var result;
asyncFunction()
.then(() { result = ...; })
.whenComplete(() { continueResync() }); // the "Done" message
resync(timeout); // waiting with a timeout as maximum limit
// Either we arrive here with the [result] filled in or a with a [TimeoutException].
return result;
}
The resync() does the same that would normally happen after ending the main method of an isolate, it starts executing the queued asynchronous functions (or waits for events to make them executable). As soon as it encounters a continueResync() call a flag is set which stops this asynchronous execution and resync() returns to the main thread. If no continueResync() call is encountered during the given timeout period it too aborts the asynchronous execution and leaves resync() with a TimeoutException.
For some groups of software which benefit from straight synchronous programing (not the client software and not the server software) such a feature would solve lots of problems for the programer who has to deal with asynchrounous-only libraries.
I believe that I have also found a solution for the main argument in lm's argumentation below. Therefore my question still stands with respect to this "enhanced" solution which I proposed: Is there anything which really makes it impossible to implement that in Dart?
The only time that you can wrap an async method in a synchronous one is when you don't need to get a return value.
For example if you want to disable the save button, save results to the server asynchronously and re-enable the save button when the job is done you can write it like this:
Future<bool> save() async {
// save changes async here
return true;
}
void saveClicked() {
saveButton.enabled = false;
save()
.then((success) => window.alert(success ? 'Saved' : 'Failed'))
.catchError((e) => window.alert(e))
.whenComplete(() { saveButton.enabled = true; });
}
Note that the saveClicked method is fully synchronous, but executes the save method asynchronously.
Note that if you make saveClicked async, not only do you have to call it using the async pattern, but the entire method body will run asynchronously so the save button will not be disabled when the function returns.
For completeness the async version of saveClicked looks like this:
Future<Null> saveClicked() async {
saveButton.enabled = false;
try {
bool success = await save();
window.alert(success ? 'Saved' : 'Failed');
}
catch (e) {
window.alert(e);
}
finally {
saveButton.enabled = true;
}
}
Yes, this is way late, but I think this is a cool feature new people should know about.
There is a way, but the Dart docs warn against it (and it's somehow "experimental", although the implications aren't really discussed).
The waitFor command.
You basically pass in an asynchronous function that returns a Future, an optional timeout parameter, and the waitFor function will return the result.
For example:
final int number = waitFor<int>(someAsyncThatReturnsInt);
The resync function cannot be implemented in Dart's current execution model.
Asynchronous execution is contagious. A synchronous function must return before any other asynchronous events can execute, so there is no way to synchronously wait for asynchronous execution.
Execution in Dart is single-threaded and event based. There is no way for the resync function to block without it also blocking all other execution in the same isolate, so the pending async operations will never happen.
To block the synchronous execution, and continue executing something else, you need to preserve the entire call stack up to that point, and reinstate it later when the synchronous operations have completed. If you have that functionality, then there are probably better ways to do things than Future and Stream :)
Also, waiting for "all async execution" isn't well-defined in an event based system. There might be a broadcast Stream emitting events coming in from the network, a periodic timer, or a receive port getting data from another isolate, or some other source of events that you can't wait for because they come from outside the isolate, or event the process. When the current isolate shuts down, it might send a final shut-down message to another isolate, so effectively the "async execution" isn't over until the isolate dies.
Using the async/await syntax, you won't get synchronous operation, but it will be easier to code the similar asynchronous operation:
function() async {
var result = await asyncFunction();
return result;
}
It won't wait for async operations that aren't reflected in the Future returned by asyncFunction, but that's the job of asyncFunction to not complete until its operations are complete.
Dart is inherently async. Trying to avoid asynchronity won't work out.
There are sync versions of some API calls for example in dart:io and in some situations it might seem simpler to use them instead but because there aren't sync versions for all methods/functions you can't avoid async entirely.
With the recent introduction of the async/await feature programming async become much simpler and the code looks almost like sync code (but it isn't).
If a call went async it stays async. As far as I know there is nothing you can do about it.
import 'package:synchronized_lite/synchronized_lite.dart';
import 'dart:async';
// Using Lock as a mixin to further mimic Java-style synchronized blocks
class SomeActivity with Lock {
bool _started = false;
Future<bool> start() async {
// It's correct to return a Future returned by synchronized()
return synchronized(() async {
if(_started)
return false;
// perform the start operation
await Future.delayed(Duration(seconds: 1));
print("Started");
_started = true;
return true;
});
}
Future<void> stop() async {
// It's also correct to await a synchronized() call before returning
// It's incorrect to neither await a synchronized() call nor return its Future.
await synchronized(() async {
if(!_started)
return;
// perform the stop operation`enter code here`
await Future.delayed(Duration(seconds: 1));
print("Stopped");
_started = false;
});
}
}
// Prints:
// Started
// Stopped
main() async {
var a = SomeActivity();
print("Hello");
a.start();
a.start();
a.stop();
await a.stop();
}
/*Since the Await statement can be used in only asynchronous methods. Then we do two methods.I thinking first we call the async method and then we constantly query the null result for the non-async method. Then we get a synchronized model. In this way, we will wait for the answer in the non-async method. Such a method comes to my mind. But as far as I can see, there is no escape from the async working model in flutter dart language. Need to get used to it.It may be unprofessional, but I wanted to share the solution that came to my mind. hope it helps.
Stock resultStockQueryByBarcodeAsync;
bool waitStockQueryByBarcodeAsyncCompleted = false;
Stock WaitStockQueryByBarcodeAsync(String barcode, int timeOut) {
CallStockQueryByBarcodeAsync(barcode);
var startTime = new DateTime.now();
while (!waitStockQueryByBarcodeAsyncCompleted) {
Duration difference = DateTime.now().difference(startTime);
if (difference.inMilliseconds > timeOut) {
throw TimeoutException("Timeout Exceeded");
}
//we must scope time. Because it can be enter endless loop.
}
return resultStockQueryByBarcodeAsync;
}
void CallStockQueryByBarcodeAsync(String barcode) async {
waitStockQueryByBarcodeAsyncCompleted = false;
resultStockQueryByBarcodeAsync = null;
var stock = await StockQueryByBarcodeAsync(barcode);/*your target async method*/
waitStockQueryByBarcodeAsyncCompleted = true;
resultStockQueryByBarcodeAsync = stock;
}
In my case, I had to initialize the database connection from constructor. I am pretty new in Flutter and I don't know what are the best practices right now. But, here is what I did.
class Storage {
late Database database;
Storage() {
getConnection().then((value) => database = value);
}
Future<Database> getConnection() async {
return await openDatabase('ims.db');
}
}
All I have done, is used the callback method to assign the value when the value is available.
Here's a solution based on staggering the start of the async function with start times at least 1 second apart, when calls come in almost simultaneously.
Steps:
Use the lastKnownTime to calculate the delta, where the initial value is 0
Once the delta is not some huge number, you know it's a duplicate call.
class StartConversationState extends State<StartConversationStatefulWidget> {
#override
Widget build(BuildContext context) {
_delayPush(); // this is the call that gets triggered multiple times
}
int lastKnownTime = 0;
int delayMillis = 3000;
_delayPush() async {
delayMillis += 1500;
await new Future.delayed(Duration(milliseconds: delayMillis));
int millisSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
int delta = millisSinceEpoch - lastKnownTime;
// if delta is less than 10 seconds, means it was a subsequent interval
if (delta < 10000) {
print('_delayPush() , SKIPPING DUPLICATE CALL');
return;
}
// here is the logic you don't want to duplicate
// eg, insert DB record and navigate to next screen
}

How to block until an async function completes [duplicate]

I'm on the way to evaluate Dart for a German company by porting various Java programs to Dart and compare and analyze the results. In the browser Dart wins hands down. For server software performance seemed to be a serious isssue (see this question of me) but that got mostly defused.
Now I'm in the area of porting some "simple" command-line tools where I did not expect any serious problems at all but there is at least one. Some of the tools do make HTTP requests to collect some data and the stand-alone Dart virtual machine only supports them in an asynchronous fashion. Looking through all I could find it does not seem to be possible to use any asynchronous call in a mostly synchronous software.
I understand that I could restructure the available synchronous software into an asynchronous one. But this would transform a well-designed piece of software into something less readable and more difficult to debug and maintain. For some software pieces this just does not make sense.
My question: Is there an (overlooked by me) way to embed an asynchronous call into a synchronously called method?
I imagine that it would not be to difficult to provide a system call, usable only from within the main thread, which just transfers the execution to the whole list of queued asynchronous function calls (without having to end the main thread first) and as soon as the last one got executed returns and continues the main thread.
Something which might look like this:
var synchFunction() {
var result;
asyncFunction().then(() { result = ...; });
resync(); // the system call to move to and wait out all async execution
return result;
}
Having such a method would simplify the lib APIs as well. Most "sync" calls could be removed because the re-synchronisation call would do the job. It seems to be such a logical idea that I still think it somehow exists and I have missed it. Or is there a serious reason why that would not work?
After thinking about the received answer from lm (see below) for two days I still do not understand why the encapsulation of an asynchronous Dart call into a synchronous one should not be possible. It is done in the "normal" synchronous programing world all the time. Usually you can wait for a resynchronization by either getting a "Done" from the asynchronous routine or if something fails continue after a timeout.
With that in mind my first proposal could be enhanced like that:
var synchFunction() {
var result;
asyncFunction()
.then(() { result = ...; })
.whenComplete(() { continueResync() }); // the "Done" message
resync(timeout); // waiting with a timeout as maximum limit
// Either we arrive here with the [result] filled in or a with a [TimeoutException].
return result;
}
The resync() does the same that would normally happen after ending the main method of an isolate, it starts executing the queued asynchronous functions (or waits for events to make them executable). As soon as it encounters a continueResync() call a flag is set which stops this asynchronous execution and resync() returns to the main thread. If no continueResync() call is encountered during the given timeout period it too aborts the asynchronous execution and leaves resync() with a TimeoutException.
For some groups of software which benefit from straight synchronous programing (not the client software and not the server software) such a feature would solve lots of problems for the programer who has to deal with asynchrounous-only libraries.
I believe that I have also found a solution for the main argument in lm's argumentation below. Therefore my question still stands with respect to this "enhanced" solution which I proposed: Is there anything which really makes it impossible to implement that in Dart?
The only time that you can wrap an async method in a synchronous one is when you don't need to get a return value.
For example if you want to disable the save button, save results to the server asynchronously and re-enable the save button when the job is done you can write it like this:
Future<bool> save() async {
// save changes async here
return true;
}
void saveClicked() {
saveButton.enabled = false;
save()
.then((success) => window.alert(success ? 'Saved' : 'Failed'))
.catchError((e) => window.alert(e))
.whenComplete(() { saveButton.enabled = true; });
}
Note that the saveClicked method is fully synchronous, but executes the save method asynchronously.
Note that if you make saveClicked async, not only do you have to call it using the async pattern, but the entire method body will run asynchronously so the save button will not be disabled when the function returns.
For completeness the async version of saveClicked looks like this:
Future<Null> saveClicked() async {
saveButton.enabled = false;
try {
bool success = await save();
window.alert(success ? 'Saved' : 'Failed');
}
catch (e) {
window.alert(e);
}
finally {
saveButton.enabled = true;
}
}
Yes, this is way late, but I think this is a cool feature new people should know about.
There is a way, but the Dart docs warn against it (and it's somehow "experimental", although the implications aren't really discussed).
The waitFor command.
You basically pass in an asynchronous function that returns a Future, an optional timeout parameter, and the waitFor function will return the result.
For example:
final int number = waitFor<int>(someAsyncThatReturnsInt);
The resync function cannot be implemented in Dart's current execution model.
Asynchronous execution is contagious. A synchronous function must return before any other asynchronous events can execute, so there is no way to synchronously wait for asynchronous execution.
Execution in Dart is single-threaded and event based. There is no way for the resync function to block without it also blocking all other execution in the same isolate, so the pending async operations will never happen.
To block the synchronous execution, and continue executing something else, you need to preserve the entire call stack up to that point, and reinstate it later when the synchronous operations have completed. If you have that functionality, then there are probably better ways to do things than Future and Stream :)
Also, waiting for "all async execution" isn't well-defined in an event based system. There might be a broadcast Stream emitting events coming in from the network, a periodic timer, or a receive port getting data from another isolate, or some other source of events that you can't wait for because they come from outside the isolate, or event the process. When the current isolate shuts down, it might send a final shut-down message to another isolate, so effectively the "async execution" isn't over until the isolate dies.
Using the async/await syntax, you won't get synchronous operation, but it will be easier to code the similar asynchronous operation:
function() async {
var result = await asyncFunction();
return result;
}
It won't wait for async operations that aren't reflected in the Future returned by asyncFunction, but that's the job of asyncFunction to not complete until its operations are complete.
Dart is inherently async. Trying to avoid asynchronity won't work out.
There are sync versions of some API calls for example in dart:io and in some situations it might seem simpler to use them instead but because there aren't sync versions for all methods/functions you can't avoid async entirely.
With the recent introduction of the async/await feature programming async become much simpler and the code looks almost like sync code (but it isn't).
If a call went async it stays async. As far as I know there is nothing you can do about it.
import 'package:synchronized_lite/synchronized_lite.dart';
import 'dart:async';
// Using Lock as a mixin to further mimic Java-style synchronized blocks
class SomeActivity with Lock {
bool _started = false;
Future<bool> start() async {
// It's correct to return a Future returned by synchronized()
return synchronized(() async {
if(_started)
return false;
// perform the start operation
await Future.delayed(Duration(seconds: 1));
print("Started");
_started = true;
return true;
});
}
Future<void> stop() async {
// It's also correct to await a synchronized() call before returning
// It's incorrect to neither await a synchronized() call nor return its Future.
await synchronized(() async {
if(!_started)
return;
// perform the stop operation`enter code here`
await Future.delayed(Duration(seconds: 1));
print("Stopped");
_started = false;
});
}
}
// Prints:
// Started
// Stopped
main() async {
var a = SomeActivity();
print("Hello");
a.start();
a.start();
a.stop();
await a.stop();
}
/*Since the Await statement can be used in only asynchronous methods. Then we do two methods.I thinking first we call the async method and then we constantly query the null result for the non-async method. Then we get a synchronized model. In this way, we will wait for the answer in the non-async method. Such a method comes to my mind. But as far as I can see, there is no escape from the async working model in flutter dart language. Need to get used to it.It may be unprofessional, but I wanted to share the solution that came to my mind. hope it helps.
Stock resultStockQueryByBarcodeAsync;
bool waitStockQueryByBarcodeAsyncCompleted = false;
Stock WaitStockQueryByBarcodeAsync(String barcode, int timeOut) {
CallStockQueryByBarcodeAsync(barcode);
var startTime = new DateTime.now();
while (!waitStockQueryByBarcodeAsyncCompleted) {
Duration difference = DateTime.now().difference(startTime);
if (difference.inMilliseconds > timeOut) {
throw TimeoutException("Timeout Exceeded");
}
//we must scope time. Because it can be enter endless loop.
}
return resultStockQueryByBarcodeAsync;
}
void CallStockQueryByBarcodeAsync(String barcode) async {
waitStockQueryByBarcodeAsyncCompleted = false;
resultStockQueryByBarcodeAsync = null;
var stock = await StockQueryByBarcodeAsync(barcode);/*your target async method*/
waitStockQueryByBarcodeAsyncCompleted = true;
resultStockQueryByBarcodeAsync = stock;
}
In my case, I had to initialize the database connection from constructor. I am pretty new in Flutter and I don't know what are the best practices right now. But, here is what I did.
class Storage {
late Database database;
Storage() {
getConnection().then((value) => database = value);
}
Future<Database> getConnection() async {
return await openDatabase('ims.db');
}
}
All I have done, is used the callback method to assign the value when the value is available.
Here's a solution based on staggering the start of the async function with start times at least 1 second apart, when calls come in almost simultaneously.
Steps:
Use the lastKnownTime to calculate the delta, where the initial value is 0
Once the delta is not some huge number, you know it's a duplicate call.
class StartConversationState extends State<StartConversationStatefulWidget> {
#override
Widget build(BuildContext context) {
_delayPush(); // this is the call that gets triggered multiple times
}
int lastKnownTime = 0;
int delayMillis = 3000;
_delayPush() async {
delayMillis += 1500;
await new Future.delayed(Duration(milliseconds: delayMillis));
int millisSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
int delta = millisSinceEpoch - lastKnownTime;
// if delta is less than 10 seconds, means it was a subsequent interval
if (delta < 10000) {
print('_delayPush() , SKIPPING DUPLICATE CALL');
return;
}
// here is the logic you don't want to duplicate
// eg, insert DB record and navigate to next screen
}

How to make an expect statement be condition for if statement

I'm currently finding the current url with
expect(browser.getCurrentUrl()).toEqual("example.com");
I want to make it into an if statement that would the url as the condition. How could I do that?
if(browser.driver.getCurrentUrl().toEqual("example.com") == "example.com"){
//do stuff
}
This is what I tried and it did not work
getCurrentUrl() is a promise, so you need to resolve it yourself to use the value as a conditional.
browser.getCurrentUrl().then((url) => {
if(~url.indexOf('example.com')) {
// code
}
else {
// code
}
})
Finally, Jasmine methods like toEqual should be used strictly with test assertions. I wouldn't use them outside of an expect statement like you have above.

.bind("move_node.jstree",.. -> data.rslt.obj undefined. How to get node data?

I have a custom functionality for check_move:
crrm : {
move : {
"check_move" : function (m) {
var p = this._get_parent(m.o);
if(!p)
return false;
if(m.cr===-1)
return false;
return true;
}
}
},
This seems to work as intended.
I then try to bind to the "move_node" event to update my database:
.bind("move_node.jstree",function(event,data){
if(data.rslt.obj.attr("id")==""){
/* I omitted this snippet from this paste - it's really long and it basically does the same thing as below, just gets the node's id in a more complicated way*/
} else {
controller.moveNode(data.rslt.obj.attr("id"),data.inst._get_parent(this).attr("id"),data.rslt.obj.attr("rel"));
}
})
This results in an error. data.rslt.obj is undefined. I'm truly at loss at what to do, I've binded to multiple events before and this is how I've done it.
How can I get node attributes etc after the move_node event, if data.rslt.obj doesn't work?
Oh, the controller.moveNode() is one of my own functions, so don't just copy-paste if you're trying to learn jstree.
I found the answer to my own question pretty soon after asking about it (typical).
One must use data.rslt.o.attr("id") instead of -.obj.- An odd inconsistency if you ask me.
I would delete this post, but I think this could be a pretty common problem. If someone thinks otherwise, feel free to delete.
if(!p)
return false;
if(m.cr===-1)
return false;
return true;
next time try to do it like this:
return (p && m.cr !== -1);