3

I have an ES6 class hierarchy. All of the classes in the hierarchy implement a draw() method. Some implement it synchronously but some need this method to be async.
How can I call draw() correctly in this sort of setup?
Is it possible to find if the method being called is async and only then call await on it's result?

shoosh
  • 76,898
  • 55
  • 205
  • 325

3 Answers3

3

You could check if the draw() has a .then function since all promises will have to implement that. If it does, use async, else execute directly

Check this answer on how to determine a promise How do I tell if an object is a Promise?

  if(draw.then) {  // all async await functions wrap the return into promises. So, this should 
    const resolvedData = await draw(); // store the data if you need to get the value
  else
    draw()
Dhananjai Pai
  • 5,914
  • 1
  • 10
  • 25
  • Is the function itself a `Promise` or is it's return value a `Promise` ? – shoosh Oct 06 '19 at 10:06
  • This seem to be wrong. The async function doesn't have `then` – shoosh Oct 06 '19 at 10:11
  • @shoosh I'm not the original answerer, but you'll need to call `.then()` on the _return_, not the `draw` function itself. All `async` functions will implicitly return a promise, and so I imagine this will work. – Nick Parsons Oct 06 '19 at 10:14
  • 1
    @NickParsons that seems like the best answer – shoosh Oct 06 '19 at 10:15
  • But I assume the draw to be a variable storing the async function, so, it should have draw().then for it to be used as a promise ? – Dhananjai Pai Oct 06 '19 at 10:20
2

I wanted to avoid having to decla(r)e 100 methods as async for the sake of just the two that actually need it.

A function doesn't have to be async (ie: return a promise) to be awaited. A synchronous function can be awaited too. This means that if a promise is not returned by draw() (ie: your draw() method is synchronous), then the await will convert the returned value of draw() to a resolved promise which it then waits for and retrieves its value.

So, something like the following is possible:

function foo() { // returns a string
  return "foo";
}

async function bar() { // implicitly returns a promise
  return "bar"; 
}

(async function() {
  const fooStr = await foo(); // foo() is synchronous, but can be `await`ed still
  const barStr = await bar(); // bar() is asynchronous, and can be `await`ed
  console.log(fooStr, barStr);
})();

With this in mind, you don't need to know if draw() is synchronous or not, instead, you can always await the draw() method, regardless of its return type.

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
1

You can check your function if it is async function by using Object.prototype.constructor.name.

var object = {
  draw: async function() {}
}
var object1 = {
  draw: function() {}
}

console.log(object.draw.constructor.name);
console.log(object1.draw.constructor.name);
Diamond
  • 3,470
  • 2
  • 19
  • 39