async functions always return a promise, so you don't need to explicitly create one yourself. Any non-promise value returned from an async function is implicitly wrapped in a promise.
Inside the foo function, you just need to await the call coreApiObject.getTeams(...) and to catch and handle any error, use the try-catch block.
Your code can be simplified as shown below:
const foo = async() => { try { const teams = await coreApiObject.getTeams(currProject.id); return teams; } catch (e) { // handle error } }
If you want to the calling code to handle the error, then you can use one of the following options:
Remove the try-catch block and just return the result of coreApiObject.getTeams(...).
const foo = async() => { return coreApiObject.getTeams(currProject.id); }
Removing the try-catch block and just returning the call to coreApiObject.getTeams(...) will allow the calling code to handle the error because the promise returned by the foo function will get resolved to the promise returned by coreApiObject.getTeams(...); this means that the fate of the promise returned by the foo function will depend on whatever happens to the promise returned by coreApiObject.getTeams(...).
If the promise returned by coreApiObject.getTeams(...) is rejected, promise returned by the foo function will also be rejected and hence the calling code will have a change to catch the promise rejection and handle it.
Throw the error from the catch block.
const foo = async() => { try { const teams = await coreApiObject.getTeams(currProject.id); return teams; } catch (error) { // throw the error throw error; } }
Other option is to throw the error from the catch block to make sure that the promise returned by the async function is rejected.
If you don't throw the error or return a promise or a thenable that is rejected, returning any other value from the catch block will fulfil the promise returned by the async function with whatever value is returned inside the catch block.