psychopy.org | Reference | Downloads | Github

Cannot read property '0' after video plays

Hello,

I am working on an experiment where my participants are asked to watch a series of videos and press specified keys in response to certain behaviors. They receive a series of instructions, and then they watch a 40 second video clip. After the clip, they receive feedback about the number of correct or incorrect responses they made.

The problem I am having is after the video plays, I am getting the following error:

TypeError: Cannot read property ‘0’ of undefined.

I should note that the error does not happen all of the time. If, in PsychoPy, I have the video set to run for significantly shorter (i.e. 20 seconds instead of the entire 40 second clip), I do not get this error at all when I run it in Pavlovia. It only occurs if the video is set to run for close to (I have had the error occur at 39 seconds) or the entire 40 seconds.

When I look at the console, I am being directed to this line of code:

if ((correctRange[currIndex][0] < currTime) && (currTime < correctRange[currIndex][1])) {

Here, I am asking the program to check if I am within a range of time that I have defined elsewhere. If I am, and there is a key pressed by the participant, code following this will look to see if it is the correct key, add to correct, etc.

Thank you in advance!

Can you post the full console error message including the traceback? What file is that line of code in?

I don’t know what exactly is going wrong, but I can explain a likely reason why you only get the error when the experiment runs for a certain time.

When Python or JavaScript evaluate conditional statements involving “and”/&&, they do it in a clever way. Say I write

if (is_raining && is_sad) { play_music('Raindrops keep failling on my head') }

The only way is_raining && is_sad is going to be true is if both is_raining is true (or ‘truthy’, but that’s not too important now) and is_sad is true. So when JS evaluates the if statement it first checks is_raining. If that turns out to be false, then there’s no point in checking is_sad, because no matter what value is_sad has, is_raining && is_sad will evaluate to false (unless it throws an error).

What does this mean for you? You have

if ((correctRange[currIndex][0] < currTime) && (currTime < correctRange[currIndex][1])) 

If correctRange[currIndex][0] < currTime evaluates to false, then your code won’t bother to check currTime < correctRange[currIndex][1]). But once correctRange[currIndex][0] stops being greater than currTime, your code has to evaluate currTime < correctRange[currIndex][1]) to see if that is true as well. So probably correctRange[currIndex][1] isn’t defined, ie correctRange[currIndex] only has a single element. But it’s just an educated guess.

This is the error I am getting in the console

image

Here is the code: https://gitlab.pavlovia.org/edayton0620/new_experiment

It looks like it is happening within the JS experiment.js

Thank you so much!

That’s really helpful. Thank you! What do you think might be a better solution? If I use an or statement, it does not read the rest of my code. It stays within the current index and never changes to the next.

Here is the code: https://gitlab.pavlovia.org/edayton0620/new_experiment

That link doesn’t work, unfortunately. I think your project is accessible through that URL only to you :slight_smile: But I haven’t used pavlovia much so I’m not sure.

What do you think might be a better solution? If I use an or statement, it does not read the rest of my code. It stays within the current index and never changes to the next.

You described that your intent with the if statement is “to check if I am within a range of time that I have defined elsewhere”. Should correctRange then be an array/list of sub-arrays (tuples/lists)? Something like [ [0, 100], [300, 500] ] (this example would be an array that holds two sub-arrays, which have two elements each)? If my guess were to be correct, then correctRange doesn’t seem to hold subarrays that always have two elements, and instead at least one of them has only one element.

You could try adding some code that prints out correctRange, so you can test to see if it is or isn’t what you want it to be. If you can edit the JS code directly, then you could test inserting e. g. console.log(correctRange) just after where you initialize (pass values to) correctRange, then run the experiment. With vanilla JS, you would then get a dialog box when visiting the site with the JS, showing the relevant information, but I don’t know if this works with PsychoPy or if it will produce an error without showing you the pop-up.

Sorry…the changes to make it public did not save. This link will hopefully work better: https://gitlab.pavlovia.org/edayton0620/new_experiment

I believe my correctRange is already an arrays/sub-array. They look like this:

correctRange = [[1.33, 1.83], [2.97, 3.47], [4.07, 4.57], [5.23, 5.73], [9.2, 9.7], [13.14, 13.64], [14.64, 15.14], [31.4, 31.9], [34.01, 34.51], [37.61, 38.11], [39.59, 40.00]];

When I have the && statement, the correctRange is what I want it to be. It shows the pair, and it changes to the next range for each key press. But I am still getting the error. As soon as I remove the &&, the error goes away, but it does not go through each range of time.

This link will hopefully work better: https://gitlab.pavlovia.org/edayton0620/new_experiment

Yes, that works great now.

I believe my correctRange is already an arrays/sub-array. They look like this:
correctRange = [[1.33, 1.83], [2.97, 3.47], [4.07, 4.57], [5.23, 5.73], [9.2, 9.7], [13.14, 13.64], [14.64, 15.14], [31.4, 31.9], [34.01, 34.51], [37.61, 38.11], [39.59, 40.00]];

Yes, you’re right, I was mistaken. The issue you get doesn’t have to do with what I described about how the && operator works. It’s likely that the problem instead is simply that currIndexis incremented to a value higher than the number of sub-arrays that are in correctRange.

Did you add the JS code related to currIndex yourself? Looking at it, it seems like currIndex is always just incremented (currIndex += 1) and never reset to 0. That means it will just keep increasing and eventually you will get a situation where you have e. g. 19 elements in your currentRange, but currIndex has a value of 19, meaning currentRange[currIndex] tries to fetch the twentieth element of currentRange, which doesn’t exist (is undefined). Trying to then fetch the zeroth element ([0]) of something that’s undefined doesn’t make sense to JS, so correctRange[currIndex][0] leads to the error Cannot read property ‘0’ of undefined.. At least I think that’s what’s going on.

This makes total sense. I did put the code in myself. I’m pretty new to both Python and JS…is there a way I could reset it to 0 once it gets to the end of the elements, even if all of my correctRanges are different lengths? I want it to run through each of the correctRange pairs and reset to 0 before it tries to get the element that is undefined.

If I correctly understand what you want, then you could add this if statement so that it’s run after every iteration/time that currIndex has been incremented.

if (currIndex >= correctRange.length) {
    currIndex = 0;
}

Example: correctRange has 10 elements. When currIndex is incremented (during the tenth iteration) to 10, it will be reset to 0.

Do note that there isn’t anything here that triggers PsychoPy/the JS code to proceed to the next video or to the next set of correctRange values, so you’ll have to make sure that happens some other way, if you haven’t already seen to it.

I’ll definitely give that a try. Thanks for all of your help!