ProGirlXOXO
ProGirlXOXO

Reputation: 2300

CasperJS continue inside for loop

I have copied this example in CasperJS.
How would I implement a 'continue' command in combination?

casper.then(function() {
    var current = 1;
    var end = 4;
    var something = true;

    for (;current < end;) {

      (function(cntr) {
        casper.thenOpen('about:blank', function() {
              this.echo('loop number: '+ cntr);

        });
        casper.then(function(){
            if (something) {
                continue; // ERROR: 'continue' is only valid inside a loop statement
            }
        });
        casper.then(function(){
            this.echo('this still gets printed');
        });
      })(current);
      current++;
    }
});

I'm getting a 'only valid inside a loop' error but... it is inside a loop?

Upvotes: 2

Views: 1128

Answers (4)

Artjom B.
Artjom B.

Reputation: 61892

All casper.then* and casper.wait* functions are asynchronous. The step functions that you pass into them are in fact executed after the loop has finished. Therefore you cannot use continue to jump to the next iteration.

You can however nest all step functions, which achieves what you expect:

casper.then(function() {
    var current = 1;
    var end = 4;
    var something = true;

    while(current < end) {

        (function(cntr) {
            casper.thenOpen('about:blank', function() {
                this.echo('loop number: '+ cntr);
            });
            casper.then(function(){
                if (something) {
                    return; // this replaced `continue`
                }
                // more synchronous code
                this.then(function(){
                    this.echo('this still gets printed');
                });
            });
        })(current);
        current++;
    }
});

It's a bit shorter at the expense of one additional indentation level.

Upvotes: 2

ProGirlXOXO
ProGirlXOXO

Reputation: 2300

This solution works but I'm not very happy about it. Added an if/else to every casper.then section with a global skip variable. As soon as a continue condition is met all following casper.thens are effectively skipped. Skip is reset at the start of each loop.

casper.start();
    casper.then(function() {
        var current = 1;
        var end = 4;
        var skip;

    for (;current < end;) {
      (function(cntr) {
        casper.thenOpen('about:blank', function() {
              this.echo('loop number: '+ cntr);
              skip = false;
        });
        casper.then(function(){
            if (skip) {
                this.echo('skipping');
            }
            else {
                // put all code here that was in casper.then
                this.echo('proceed as normal');
                skip = true;

            }
        });

        casper.then(function(){
            if (skip) {
                this.echo('skipping');
            }
            else {
                // put all code here that was in casper.then
                this.echo('this no longer gets printed');
            }
        });
      })(current);
      current++;
    }
});

Upvotes: 1

Ruan Mendes
Ruan Mendes

Reputation: 92274

Once you are inside an inner function (you actually have two levels, the IIFE around the body of the loop and the function you're passing to thenOpen), you're no longer in the scope of the loop.

Also, the functions that are passed to casper.then and casper.thenOpen execute asynchronously (but in order). If you want to affect the order, you have to check values from within those functions.

casper.then(function() {
    var current = 1;
    var end = 4;
    var something = true;
    var shouldContinue = false;

    for (;current < end;) {

      (function(cntr) {
        casper.thenOpen('about:blank', function() {
          shouldContinue = false;
          this.echo('loop number: '+ cntr);    
        });
      })(current, s);

      (function(cntr) {
        casper.then(function(){
          if (something) {
            shouldContinue = true;
          }
        });
      })(current);


      (function(cntr) {
        if (shouldContinue) {
            return;
        }
        casper.then(function(){
          this.echo('this still gets printed');
        });
      })(current);

      current++;
    }
});

Upvotes: 1

smnbbrv
smnbbrv

Reputation: 24531

It is not inside the loop. When you isolate your scope with an anonymous function you lose the "loop scope" reference, so your continue does not know where the loop is. Although you can use closures (variables outside of the functions scope), you can't refer an outside loop...

See in the console:

for (var i=0;i<10;i++) continue;

works like a charm, when

for (var i=0;i<10;i++) (function(){ continue; })();

does not work because the loop reference is lost.

How to deal with that? Just return a result from your function, e.g.

for (var i=0;i<10;i++) {
  if ((function(){ return i === 3; })()) {
    console.log('continued'); 
    continue;
  }
}

Upvotes: 1

Related Questions