1

I am trying to make an async await function work in a class, but while my delegated event handlers fire, somehow the variable this.shows inside the assigned function is undefined.

this.shows.length in previousRangeShows() returns 0 because this.shows is empty, but getShows() returns the shows properly with a length of 101.

export default class Shows {

  constructor() {
    console.log('Created Shows')
    this.RANGE = 4
    this.shows = []
    this.position = 0;
    shows.setupDelegatedEventHandlers()
  }

  async getShows() {
    console.log('Getting shows from JSON...')
    this.shows = await $.getJSON('../json/shows.json')
    this.position = this.shows.length - this.RANGE
    this.renderSelectionOfShows(this.position, this.shows.length)
    console.log('this.shows.length: ', this.shows.length)
  }

  nextRangeShows() {
    console.log('>>> next shows')
    if (this.position + 1 + this.RANGE < this.shows.length) {
      this.position += this.RANGE
      $('main').html = ''
      this.renderSelectionOfShows(this.position, this.RANGE)
    }
  }

  previousRangeShows() {
    console.log('<<< previous shows')
    if (this.position > 0) {
      this.position -= this.RANGE
      $('main').html = ''
      this.renderSelectionOfShows(this.position, this.RANGE)
    }
  }

  setupDelegatedEventHandlers() {
    $('main').on('click', '#left-arrow', this.previousRangeShows)
    $('main').on('click', '#right-arrow', this.nextRangeShows)
  }

  renderSelectionOfShows(start, range) {
    $('main').append(`<img class="arrow" id="left-arrow" src="../images/left_bracket_white.png">`)
    for (let i = start; i < range; i++) {
      $('main').append(`<div id="shows"><p>
        <strong>${this.shows[i].film}</strong><br>
        Saloon: ${this.shows[i].auditorium}<br>
        ${this.shows[i].date} - ${this.shows[i].time}
        </p></div>`)
    }
    $('main').append(`<img class="arrow" id="right-arrow" src="../images/right_bracket_white.png">`)
  }

  renderAllShows() { //unused
    for (let show of this.shows) {
      $('main').append(`<p>
        Movie: <strong> ${show.film} </strong><br>
        Saloon: ${show.auditorium}<br>
        Date: ${show.date} - ${show.time}
        </p>`)
    }

  }
}```
noumenal
  • 885
  • 1
  • 10
  • 31
  • `$('main').on('click', '#left-arrow', this.previousRangeShows)` -> `$('main').on('click', '#left-arrow', () => this.previousRangeShows)` or `$('main').on('click', '#left-arrow', this.previousRangeShows.bind(this))`. I prefer the former. – VLAZ Mar 12 '21 at 13:23
  • @VLAZ That's not the problem. The event handlers are firing as they should. The problem is that the function previousRangeShows has this.shows as undefined. – noumenal Mar 12 '21 at 13:59
  • The problem you describe is `this` having incorrect value when the callback executes. The value of `this` is determined *at call time*. So when you pass `this.method` as callback, at calltime it's executed *without* a link to the original object where it was taken from. – VLAZ Mar 12 '21 at 14:00
  • [See demonstration](https://jsbin.com/fugizur/edit?js,console) – VLAZ Mar 12 '21 at 14:04

0 Answers0