How to exit loop after certain number of trials with JavaScript?

I’m using the builder to build an online experiment (running psychopy3 version 3.0.2 on a mac). I have 200+ trials set up in a loop and want to have the loop end after a certain number of random trials (e.g., 5). I’ve figured out that I can use the code snippets to do this and I got it to run correctly on my computer, but after reading a bit on here I realize it would have to be JavaScript for it to work online.

Can anyone tell me what the JS version of these python code snippets would be? I have a feeling this is probably pretty basic, but I don’t have any prior experience with Python or JS…

I have a snippet in the “begin experiment” section with:

myCount = 0

And I put this snippet in the “begin routine” section to exit the loop after 5 trial runs:

myCount = myCount + 1
if myCount > 5:
    trials_1.finished = True
    break

Please let me know if I can clarify anything. Thanks in advance.

Yes, go to your Code Component and select “Both” so you can insert JS and Python alongside each other. We’ll hopefully have some rudimentary auto-translation python->JS eventually.

In your case, I think the correct JS code would be some line-ending semi-colons:

myCount = 0;

curly brackets for your if statement and True becomes lower case:

myCount = myCount + 1;
if (myCount > 5) {
    trials_1.finished = true;
    break;
}

In Chrome and Firefox (and presumably others) you can then debug and tweak the Javascript using “developer tools”.

@dvbridges and many others have better JS coding skills than me though so they may spot errors in the above

1 Like

Thanks for the reply, Jon. Unfortunately, that code doesn’t seem to do the trick. I googled a bit more in search of a solution and noticed that most JS scripts have something like:

var myCount = 0;

So as a general question: is it necessary to write var before defining a variable in psychopy? I tried it and it still didn’t work, so that can’t be the only issue, but I’m wondering if that’s something that takes place behind the scenes in psychopy or something that we’d need to remember to write in the JS side of the Code Component console.

Anyhow, do you (or anyone else) have further ideas for troubleshooting? Any suggestions would be greatly appreciated!

PS – I used safari’s developer tools and looked at the JS console, but didn’t see any error messages. I’m not exactly sure what I should be looking for. There were a lot of warnings, but they don’t seem related to the problem:

@durkeepk, the fix to allow you to control when your loop ends is on its way.

Regarding defining variables in your code components, you do not need to define the variable with var, because PsychoPy will find and define them outside of your functions to give them global scope to be used across your experiment. If you are not seeing the variables defined as var above your functions in the JS code that PsychoPy outputs, then there must have been a problem with compiling the script.

Thanks, @dvbridges and @jon for the help!

I just downloaded version 3.0.3 and I can see that the JS works now. I can display the myCount variable each frame both online and computer-based experiment. However, when I include the JS component that @jon recommended and try to run it online, the experiment doesn’t load—I only get a blank white screen (it works if I just run it locally). I looked at the JavaScript Console in Safari and there’s an error that says:

SyntaxError: 'break' is only valid inside a switch or loop statement.

I tried a few different things like specifying which loop to break (e.g., break trials_1;) but still can’t get it work for me. I’m not sure how to proceed from here. Do you have any ideas?

I’ve only had to use ‘break’ to force an exit from a continuing loop (e.g. using ‘while’). I your case you may not need to use ‘break’ at all. Just a guess.

Hi dvbridges, just wanted to check if the fix to allow us to control when a loop ends is still in progress. Thank you!

Hi @isk017, I think loop.finished is going to be fixed so you can end your loops online, will create a GitHub issue so we can keep track of this and know what version it will be released in. See:

2 Likes

Hi all,

I’ve also been unable to conditionally break out of loop when running online.

Just wondering if anyone has discovered an alternative way of coding this while we wait for a fix?

Thanks!

I’ve been using the nReps property in Builder mode to end a loop based on number of repetitions, but needed a code block solution to break all loops (I have two - blocks & trials) once a certain amount of time had elapsed since session start (or is there a Builder solution for that?) That brought me to this thread.

While issue#34 isn’t ready, I’m resorting to killing the experiment with if ((sessDur-globalClock.getTime()) < 0){psychoJS.experiment.experimentEnded = true;}

Extreme, impolite (as it skips the “thank you” routine at the end), but works in cases like mine.

I’ve been able to use this feature to break off of my trials loop - thanks!
Where I’m having trouble is in using it for an outer loop (blocks). Any tips?

Hi David,

I saw this was fixed a few weeks ago, but I’m still having trouble getting this working.

I’ve tried a few variations of the following, but my online exp seems to skip past this line of code and do nothing:

LoopName.finished =true;

Any help appreciated!

Hi Jamie, this is working correctly, so it could be the conditional that you are using to end the loop. Can you share the code?

Hi David,

Thanks for the quick response!

Here’s the code snippet I’m trying to run.

        if (Clicked__Next.status == PsychoJS.Status.FINISHED) {
            LoopName.finished = true;
            continueRoutine = false;
        }

When users click the Next button, it briefly changes colour (0.30ms) just to give some user feedback. Once that’s finished, the routine ends and we go to the next page. I have that working fine in JS throughout all my exp, it’s just getting out of the loop I can’t get working…

I’m having the same problem.
Can we get a general guideline for “how to exit a loop after a certain number of trials in JS” ?
I think it would benefit a lot of users trying to set up online experiments.

2 Likes

Hi @Jamie, the following works. In the Each Frame tab:

if (Clicked__Next.status === PsychoJS.Status.FINISHED) {
      currentLoop.finished = true;
}

Hi David,

Thanks for the solution - but I’ve still had no luck getting this to work :disappointed:

Whilst my python code works fine:

if Clicked__Next.status == FINISHED:
            Welcome__Loop.finished=True
            continueRoutine = False

the JS equivalent does not (nothing happens, and the loop just continues indefinitely):

if (Clicked__Next.status == PsychoJS.Status.FINISHED) {
            Welcome__Loop.finished = true;
            continueRoutine = false;
}

@Jamie, would you mind sharing the URL of your project?

Hi David,

You can access the experiment here, just type “A” into the Order field:
https://run.pavlovia.org/j.adams/photonorms-2/html/

The issue arises when I implement a “Back” button into those first few instruction pages (I’ve taken this Back button out for the moment because I can’t get this working, but normally it’s to the left of the next button). In the PsychoPy builder, I have hidden duplicates of all these instructions pages, in their own loops. I.e.:

Welcome > Demographics > (Welcome Repeat > Demographics Repeat) > . Instructions 1

If P presses Next on Demographics, then we simply skip past those hidden Routines (in parentheses here) and go straight to Instructions 1. If they press “Back” on Demographics though, they will enter a loop of the blocks in parentheses x99 reps) - from here, they can click back and forward between those two routines as many times as they like, but I need to be able to break out of this loop when they (finally) wish to continue and click Next on Demographics Repeat. The Python code I posted before works perfectly with this setup (I usually have to nest these even further when I have a few pages in a row) - I just can’t seem to crack it in JS. Or maybe I’ve just coded this in the most inelegant way possible from the get go :rofl:

Thanks for the help!

Ok, well I cannot see the line of code Welcome__Loop.finished = true; in your JS script. Has it been removed?