0

I modified my question to be more specific. now i don't care about the desired behavior and i just need to correct syntax error

I was studying this tutorial I face with an error in this code.

severity: 'Error'

message: 'Property 'offset' does not exist on type 'PagerserviceProvider'.'

actually i have the same error for this three variables.

that.pageSize,that.offset,that.size

public async getPager(tableName:string,pageSize: number = 10) {
let pageSize = pageSize;
let offset = 0;
let limit = pageSize;
let size = await this.getTotal(tableName);
let that = this;
return  {
        initialPage:function(){

            return new Promise((resolve,reject)=>{
                var d = [];
                that.executeSql(tableName,limit,offset).then((data)=>{
                    console.log(JSON.stringify(data));
                    for(var i = 0 ; i < data.rows.length ; i++)
                    {
                        d.push(data.rows.item(i));
                    }
                    resolve(d);
                },(e)=>{
                    reject(e);
                });
            });

        },
        nextPage:function(){
            if(that.offset <= that.size - that.pageSize )
            {  
                that.offset +=  that.pageSize;
            }
            return new Promise((resolve,reject)=>{
                var d = [];
                that.executeSql(tableName,limit,offset).then((data)=>{
                    for(var i = 0 ; i < data.rows.length ; i++)
                    {
                        d.push(data.rows.item(i));
                    }
                    resolve(d);
                },(e)=>{
                    reject(e);
                });
            });                    
        }            
    };}
david
  • 465
  • 5
  • 11

3 Answers3

1

When you use the keyword function to declare a function, the function's this does not refer to the upper this. so using this in the function body, refers to the function itself.

The problem you are facing is related to the fact that your function is declared inside a class which already have a this defined, so you need a way to reference the upper this while being inside the nested function.

class Test {

  hello () { console.log('hello') }

  method () {
    this.hello() // It will work because `this` refers to the class
    function sayHello () {
      return this.hello()
      // it won't work because `this` refers to the function sayHello
    }
    return sayHello()
  }
}

To bypass this limitation, you can save your upper this in a variable while your code is in the upper scope. This variable is usually called that or self.

class Test {

  hello () { console.log('hello') }

  method () {
    var that = this // that is now refering to the class
    this.hello() // It will work because `this` refers to the class
    function sayHello () {
      return that.hello()
      // that is still refering to the class so it will succeed
    }
    return sayHello()
  }
}

EDIT:

another trick to avoid using that is to use ES6 arrow function. Inside an arrow function, this alway refers to the upper scope.

class Test {

  hello () { console.log('hello') }

  method () {
    this.hello() // It will work because `this` refers to the class
    // `this` refers to the upper scope by default so it works
    const sayHello = () => this.hello()
    return sayHello()
  }
}

EDIT 2:

Your code should be:

  public async getPager(tableName: string, pageSize: number = 10) {
    let pageSize = pageSize;
    let offset = 0;
    let limit = pageSize;
    let size = await this.getTotal(tableName);
    let that = this;
    return  {
        initialPage: function () {

            return new Promise((resolve,reject)=>{
                var d = [];
                that.executeSql(tableName, limit, offset).then(data => {
                    console.log(JSON.stringify(data));
                    for(var i = 0 ; i < data.rows.length ; i++) {
                        d.push(data.rows.item(i));
                    }
                    resolve(d);
                }, e => {
                    reject(e);
                });
            });

        },
        nextPage: function () {
            if(offset <= size - pageSize ) {  
                offset += pageSize;
                // no need to use `that` because you used `let`
            }
            return new Promise((resolve, reject) => {
                var d = [];
                that.executeSql(tableName, limit, offset).then(data => {
                    for(var i = 0 ; i < data.rows.length ; i++) {
                        d.push(data.rows.item(i));
                    }
                    resolve(d);
                }, e => {
                    reject(e);
                });
            });                    
        }            
      };
    }
Guillaume Badi
  • 749
  • 5
  • 15
0

'that' is just the name of a variable used to store the original value of 'this' at the start of your code, as the value of 'this' changes. The variable name could just as easily be 'dog' or 'apple'.

You might choose to use 'this' later on in your code instead if you intend to access the current value of 'this' at that point in time. Otherwise you will probably reference your original variable that stored it's value, e.g. 'that', 'dog' or 'apple'.

  • what I cant understand is ,I define the variable in the same context as the context I define "that" so "that.offset" is no meaningless – david Jul 25 '17 at 12:19
0

getPager is a method: If you call it with an already lost context, that will get the current this value, which is not pointing the correct context.

const someInstance = new SomeClass()

someInstance.getPager() // You call getPager directly from the someInstance context

someHTMLButton.onClick = someInstance.getPager // Here the getPager method lost its context

A solution is to bind getPager to someInstance. This way it will always have its context this pointing to someInstance.

someHTMLButton.onClick = someInstance.getPager.bind(someInstance)
kube
  • 13,176
  • 9
  • 34
  • 38