76

Is it or will it be possible to have an ES6 class getter return a value from an ES2017 await / async function.

class Foo {
    async get bar() {
        var result = await someAsyncOperation();

        return result;
    }
}

function someAsyncOperation() {
    return new Promise(function(resolve) {
        setTimeout(function() {
            resolve('baz');
        }, 1000);
    });
}

var foo = new Foo();

foo.bar.should.equal('baz');
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Enki
  • 1,565
  • 2
  • 13
  • 20
  • 4
    This is all you need: `get bar(){ return someAsyncOperation(); }` – Felix Kling Nov 23 '15 at 20:00
  • @FelixKling I updated my post to hopefully clarify my question. I am not trying to return a function from the getter. I want the return value to come from an async operation. – Enki Nov 23 '15 at 21:37
  • Yes, `return someAsyncOperation();` returns the promise that `someAsyncOperation` returns. It doesn't return a function (what made you think that?) – Felix Kling Nov 23 '15 at 21:38
  • 3
    I understand return someAsyncOperation(); would return a promise. I want to return the result of the promise. foo.bar should return 'baz' – Enki Nov 23 '15 at 21:47
  • 12
    It can't. You cannot return synchronously from an asynchronous function. `async/await` is just syntactic sugar around promises + generators. It lets you write code that *looks* synchronous, but it still runs asynchronously. At the top level you still have to deal with the promise. You might be able to do `await foo.bar`, but if not, you have to deal with the promise returned by `foo.bar` directly. – Felix Kling Nov 23 '15 at 21:48
  • 3
    It would be nice if you could just do: `get async functionName(){}`. I'd like the ability to await inside of a getter (directly) instead of the round-about ways answered here. – Lonnie Best Nov 25 '19 at 06:17

4 Answers4

68

Update: As others have pointed out, this doesn't really work. @kuboon has a nice workaround in an answer below here..

You can do this

class Foo {
    get bar() {
        return (async () => {
            return await someAsyncOperation();
        })();
    }
}

which again is the same as

class Foo {
    get bar() {
        return new Promise((resolve, reject) => {
            someAsyncOperation().then(result => {
                resolve(result);
            });
        })
    }
}
Fractalf
  • 5,228
  • 3
  • 23
  • 26
24

You can get the value by await on the caller side.

class Foo {
    get bar() {
        return someAsyncOperation();
    }
}
async function test(){
  let foo = new Foo, val = await foo.bar;
  val.should.equal('baz');
}
kuboon
  • 9,557
  • 3
  • 42
  • 32
16

You can only await promises, and async functions will return promises themselves.
Of course a getter can yield such a promise just as well, there's no difference from a normal value.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

For the value returned by the getter, this changes nothing, since an async function returns a Promise anyway. Where this matters, is in the function, since await can only be used in an async function.

If the issue it that await is wished in the function, I would do:

get property () {
  const self = this; // No closure with `this`, create a closure with `self`.
  async function f () { // `async` wrapper with a reference to `self`
    const x = await self.someFunction(); // Can use `await`
    // the rest with “self” in place of “this”
    return result;
  }
  return f(); // Returns a `Promise` as should do an `async get`
}
Hibou57
  • 6,870
  • 6
  • 52
  • 56