Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

this inside an async object method [duplicate]

I creating an object that uses async function methods with babel-polyfill/babel-preset-es2017, however I am having a problem with this:

let obj = () => {
    return {
        doAsync: async () => {
            let thing = await longProcess()
            return this.transform(thing)
        },

        transform: (thing) => {
            return psuedoCodeTransform(thing)
        }
    }
}

let instance = obj()
instance.doAsync()
// TypeError: cannot read property 'transform' of undefined`.

Is this something described in ES2017, a babel-polyfill/regeneratorRuntime gotcha?

like image 769
Kris Molinari Avatar asked May 23 '17 19:05

Kris Molinari


People also ask

What does async function returns?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

What does async do?

Async functions The word “async” before a function means one simple thing: a function always returns a promise. Other values are wrapped in a resolved promise automatically. So, async ensures that the function returns a promise, and wraps non-promises in it.

What async await do?

Await: Await function is used to wait for the promise. It could be used within the async block only. It makes the code wait until the promise returns a result. It only makes the async block wait.

What happens if you await a promise?

This rule applies when the await operator is used on a non-Promise value. await operator pauses the execution of the current async function until the operand Promise is resolved. When the Promise is resolved, the execution is resumed and the resolved value is used as the result of the await .


2 Answers

Arrow functions do not create their own context. They don't have their own this and this will refer to the enclosing scope's context. In this case (no pun intended), this does not refer to the same object as instance at all.

If you log this inside doAsync, you'll notice it's the window global.

like image 54
Joseph Avatar answered Sep 20 '22 13:09

Joseph


Joseph the Dreamer's response is exactly right obviously, but since I work best by example, here is your code changed which should make it work. Notice the only change is actually defining doAsync as a normal function instead of arrow function:

let obj = () => {
    return {
        doAsync: async function() {
            let thing = await longProcess()
            return this.transform(thing)
        },

        transform: (thing) => {
            return psuedoCodeTransform(thing)
        }
    }
}

let instance = obj()
instance.doAsync()
// TypeError: cannot read property 'transform' of undefined`.
like image 25
Lance Whatley Avatar answered Sep 20 '22 13:09

Lance Whatley