0

consider the following:

import request = require("request");

class CFoo {
    test:number;

    async getItem(): Promise<number> {
        var requestOptions = {
            method: 'GET',
            url: `https://www.google.com`,
            headers: { 
                'cache-control': 'no-cache'
            } 
        };
        console.log('number is ' + this.test);
        return new Promise<number>((resolve, reject)=>{
            console.log('in promise... number is ' + this.test);
            request(requestOptions, function (error, response, body) {
                console.log('in async... number is ' + this.test);
                if (error) throw new Error(error);                
                resolve(this.test);
            });
        });
    }

    constructor() {
        this.test = 555;
    }
}

var foo:CFoo = new CFoo();
foo.getItem().then(val=>console.info('returned ' + val));

As you can notice, i read value of test (555) in three situations:

  1. from the getItem() method call
  2. from the promise executor
  3. from the request() callback function.

I was surprised to notice that in #3, test is undefined!

I can understand that this is not "a thing" in the executor/callback context,
as caller can't know the object and perform __thiscall (c++ terminology).

1st question: Why wasn't test included in the closure ?
2nd question: if request callback didn't work, why did the promise executor ?

note, tried changing the lambda to anonymous function with same results.

Thanks.

Tomer W
  • 3,395
  • 2
  • 29
  • 44
  • 1
    The `this` inside the callback of `request` refers to the `function (error, response, body)`'s `this` due to how the function keyword works. Either reference the `this` outside it and access it inside the callback, either use a lambda (an arrow function) instead to keep the desired `this`. See @VLAZ's comment below for a cleaner explanation, I'm not that good with words, he did a great job though :P – briosheje Jun 28 '19 at 12:04
  • 1
    `this` is the context of the current function being executed. when you do `function (error, response, body) {` you get a new function which, when executed, will get a new context. Automatically capturing `this` in an inner function from the outer function will inherently break what `this` does, since you will never be able to nest functions. However, arrow functions have a lexically bound value of `this`, which is why `(resolve, reject)=>{` works. – VLAZ Jun 28 '19 at 12:05
  • Thanks, I didn't notice that actually lambda DOES work, thought i tried it, but i guess i had another issue then. All works perfectly now :) – Tomer W Jun 28 '19 at 12:27

1 Answers1

0

There is a little trick to remember the class scope. In the first line of getItem() just put a let me = this; and then in your nested function you could use me.test. This should work :)

arnonuem
  • 1,317
  • 6
  • 19