Reputation: 2405
UPDATE
I have read over a dozen articles on this topic and not one of them addresses this fundamental question. I am going to start listing a resources section at the end of this post.
ORIGINAL POST
My understanding of an async
function is it returns a promise.
MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Inside my program I could write something like:
function testPromise() {
return new Promise((resolve, reject) => {
// DO WORK
reject() // IF WORK FAILS
resolve() // IF WORK IS SUCCESSFUL
})
}
async function mainFunction() {
let variable
try {
variable = await testPromise()
} catch(e) {
throw e
}
return variable
}
I could also write testPromise as an async function and await
that in the same context.
async function testAsyncFunction() {
//DO WORK AND THROW ERROR IF THEY OCCUR
}
async function mainFunction() {
let variable
try {
variable = await testAsyncFunction()
} catch(e) {
throw e
}
return variable
}
Which would be considered best practice? If I wish to create asynchronous operation, should the function use return New Promise
and awaited in a async
function or is awaiting an async
function from an async
function the same difference?
RESOURCES
JavaScript ES 2017: Learn Async/Await by Example https://codeburst.io/javascript-es-2017-learn-async-await-by-example-48acc58bad65
Javascript — ES8 Introducing async/await
Functions
https://medium.com/@reasoncode/javascript-es8-introducing-async-await-functions-7a471ec7de8a
6 Reasons Why JavaScript’s Async/Await Blows Promises Away (Tutorial) https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9
----------------------CURRENT----------------------
export default function time_neo4jUpdate({ store, action, change, args, }) {
return new Promise(async (resolve, reject) => {
try {
const {
thing: { type },
nonValidatedArgs: { leapYear, root, start, end },
_neo4j,
_cypherReducers,
_neo4jCreateReduce,
_timetreeSteps: { update }
} = store.getState()
let results = []
for (let i = 0; i < _neo4jCreateReduce.length; i++) {
const result = await _neo4j.session(
_neo4jCreateReduce[i],
_cypherReducers.runQuery(update, i, root, start, end))
results = [...results, result]
}
resolve({
store,
action: 'NEO4J_UPDATE',
change: results,
args
})
} catch (e) {
const m = `NEO4J TIMETREE UPDATE: Unable to complete the UPDATE step for the timetree. WHAT: ${e}`
reject(m)
}
})
}
----------------------AS ASYNC FUNCTION----------------------
export default async function time_neo4jUpdate({ store, action, change, args, }) {
try {
const {
thing: { type },
nonValidatedArgs: { leapYear, root, start, end },
_neo4j,
_cypherReducers,
_neo4jCreateReduce,
_timetreeSteps: { update }
} = store.getState()
let results = []
for (let i = 0; i < _neo4jCreateReduce.length; i++) {
const result = await _neo4j.session(
_neo4jCreateReduce[i],
_cypherReducers.runQuery(update, i, root, start, end))
results = [...results, result]
}
return {
store,
action: 'NEO4J_UPDATE',
change: results,
args
}
} catch (e) {
const m = `NEO4J TIMETREE UPDATE: Unable to complete the UPDATE step for the timetree. WHAT: ${e}`
throw m
}
}
Upvotes: 20
Views: 6589
Reputation: 101662
Even without the availability of async
/await
, you should very rarely need to use new Promise()
. If you're using it a lot, it's typically a code smell.
The whole point of async
/await
is that it allows you to avoid a lot of the situations where you would otherwise need to work with promises explicitly.
So if it's supported in the environment you're targeting (Internet Explorer does not support async
/await
) or you're using a transpiler, go ahead and use it anywhere you can. That's what it's for.
Bear in mind that this is pointless:
catch(e) {
throw e;
}
There's no point in catching an error just to rethrow it. So if you're not actually doing anything with the caught error, don't catch it:
async function testAsyncFunction() {
//DO WORK AND THROW ERROR IF THEY OCCUR
return value
}
Edit: Now that you've provided an example of your code, I can answer with more certainty: If your function is based upon existing promises, then by all means, it is good to use async
/await
and you usually should not use new Promise()
:
export default async function time_neo4jUpdate({
store,
action,
change,
args,
}) {
try {
const {
thing: {
type
},
nonValidatedArgs: {
leapYear,
root,
start,
end
},
_neo4j,
_cypherReducers,
_neo4jCreateReduce,
_timetreeSteps: {
update
}
} = store.getState()
const results = await _neo4jCreateReduce.reduce(async function (acc, el) {
const result = await _neo4j.session(
el,
_cypherReducers.runQuery(
update,
i,
root,
start,
end
)
)
return [...(await acc), result]
}, []);
return {
store,
action: 'NEO4J_UPDATE',
change: results,
args
};
} catch (e) {
const m = `NEO4J TIMETREE UPDATE: Unable to complete the UPDATE step for the timetree. WHAT: ${e}`
throw m;
}
}
Upvotes: 7