Most idiomatic way to return a promise, or a function that returns a promise?

Viewed 54

Let's say I have an API that expects a promise as an argument:

async function doSomething(somePromise) {
  somePromise.then(someOutcome => console.log(someOutcome))
}

And let's say I have some trivial logic for something I want to pass into that API: return 'hi'

I believe these two approaches to calling the API are functionally equivalent - but is one more idiomatic/clear than the other?

/* A */ doSomething(Promise.resolve('hi'))
/* B */ doSomething((async () => 'hi')())

Now, imagine I have another API that expects a function as argument, which is expected to return a promise:

async function doSomethingElse(someFunction) {
  someFunction().then(someOutcome => console.log(someOutcome))
}

In this case, which is most idiomatic?

/* C */ doSomethingElse(() => Promise.resolve('hi'))
/* D */ doSomethingElse(async () => 'hi')

I suspect the correct answers are "A" and "D", but it feels surprising that a developer would be expected to sometimes think in terms of explicit Promises, and sometimes think in terms of async.

I had read somewhere something along the lines of "If you're typing Promise, you're probably doing something wrong". Is that a gross oversimplification?

And final question: If the API steps away from explicit promises and uses await directly (effectively supporting a promise or a value) - is that really the answer? That the API itself in my first example was the "problem" for modern idiomatic JS?

async function doSomethingThird(someValueOrPromise) {
  simpleValue = await someValueOrPromise
  console.log(simpleValue)
}
/* E */ doSomethingThird(Promise.resolve('hi'))
/* F */ doSomethingThird((async () => 'hi')())
/* G */ doSomethingThird('hi')
0 Answers
Related