NicolasL
NicolasL

Reputation: 83

Does a function need to be declared as asynchronous to return a promise?

I'm using a helper function (fetchGet) returning an asynchronous function that returns a promise (fetchWrapper). Does this helper function need to be declared as asynchronous to itself return a promise?

My case here is using fetch, which needs to be awaited in my first function fetchWrapper (simplified here for readibility):


// returns a promise
async function fetchWrapper(url, method) {
  const response = await fetch(url, {method: method});
  if (!response.ok) {
    throw new Error("HTTP error " + response.status);
  }
  return response;
}

async function fetchGet(url) {
  return fetchWrapper(url, 'GET');
}

async function getSpecificData() {
  return fetchGet('/a/specific/url');
}

Do I need to declare the fetchGet function as an asynchronous function as above, for it to return the promise?

Or could I just declare it as a normal synchronous function as below? (that would be indeed the same case for the getSpecificData function)

function fetchGet(url) {
  return fetchWrapper(url, 'GET');
}

Upvotes: 6

Views: 1521

Answers (3)

T.J. Crowder
T.J. Crowder

Reputation: 1074148

Does a function need to be declared as asynchronous to return a promise?

No, not at all. In fact, promises were around long before async functions.

Your wrapper can be just:

function fetchGet(url) {
  return fetchWrapper(url, 'GET');
}

You don't need async if you're not using await inside the function. You might choose to have it in order to flag up the asynchronous nature of the function, e.g., as in-code documentation (code hints in IDEs, etc.). But it isn't required.


Side note: You have a problem with fetchWrapper. It succeeds with the fulfillment value undefined if there's an HTTP error. That means code using it has to check the fulfillment value to see if it's undefined before using it. I'd recommend making HTTP errors errors (rejections):

async function fetchWrapper(url, method) {
  const response = await fetch(url, {method: method});
  if (!response.ok) {
    throw new Error("HTTP error " + response.status);
  }
  return response;
}

Upvotes: 8

calbertts
calbertts

Reputation: 1513

You just need to declare a function as async when inside the function you going to await for a result, so both:

// returns a Promise because it's async (resolved with 'value')
async function fetchGet(url) {
  const value = await fetchWrapper(url, 'GET');
  return value;
}

// returns a Promise because fetchWrapper is a Promise
function fetchGet(url) {
  return fetchWrapper(url, 'GET');
}

// returns a Promise, just because it's async
async function fetchGet(url) {
   // nothing
}

// returns undefined
function fetchGet(url) {
    // nothing 
}

Work exactly the same for these callers:

fetchGet('url').then(value => {...})
const value = await fetchGet(url)

Upvotes: 1

Quentin
Quentin

Reputation: 943207

Does this helper function need to be declared as asynchronous to itself return a promise?

No.

async functions always return promises, even if the return statement returns something that is not a promise. async functions let you manage other promises inside them using await

You can explicitly return a promise from any function.

Upvotes: 1

Related Questions