Reputation: 2351
I am trying to do something like this but it's breaking:
myAsyncFunction = async () => {
fetchResource().then( res => {
await fetchAnotherResource()
....
})
}
Within the completion of the first promise, I want to use await expressions, but it doesn't look like the scope of that callback allows for async functions.
With the way it is above, it tells me that await is a reserved keyword (it's not picking up any meaning for await in this case, because of scope I'm guessing?)
If I declare the anonymous function with async
like this:
fetchResource().then( async (res) => {...})
I get a syntax error like this:
ProductForm.jsx?130a:143 Uncaught (in promise) TypeError: (0 , _context.t1) is not a function
I'm not sure if it's relevant, but this is inside of a React component.
Is there a syntax for accomplishing what I'm trying to do here? (Use an async function as a promise handler)
Edit: relevant code (sorry for code dump)
initializeState = async () => {
getShopInfo(this.state.shop_id)
.then (async (res) => {
if (product_id) {
({ activeLocalization, localizations } = await this.initializeEditState(product_id, defaultLocalization, localizations))
} else {
({ activeLocalization, localizations } = await this.initializeBlankState(defaultLocalization, localizations))
}
})
}
initializeEditState = (product_id, defaultLocalization, localizations, allCategoriesPromises) => {
return new Promise( resolve => {
let productPromiseArray = []; // storage for auxiliary localization requests
let filledOutLocalizations = []; // hold localizations that have been merged with the product data
getProduct(product_id, defaultLocalization.localization_id)
.then( json => {
/* fetch object that will represent a product in state
* and merge it with the default localization object */
let defaultProductState = this.setupEditProductState(json)
defaultLocalization = Object.assign(defaultLocalization, defaultProductState)
/* setup promise array for all other localizations */
localizations.forEach( l => {
productPromiseArray.push(getProduct(product_id, l.localization_id))
})
/* fetch other products and merge them with localizations */
Promise.all( productPromiseArray )
.then( resultArray => {
resultArray.forEach( res => {
/* test for fail condition here;
* fail condition happens when new localizations
* are registered between edits */
let loc = localizations.find(
l => l.localization_id == res.data.product.localization_id
)
if (res.result) {
loc = Object.assign(loc, this.setupEditProductState(res))
} else {
/* Default state for this localization
* (you should have access to defaultLocalization) */
loc = Object.assign(defaultProductState, loc)
}
filledOutLocalizations.push(loc)
})
/* Finally, get ALL category lists and
* INITIALIZE EDIT STATE */
let promiseArray = []
for (var filLoc of filledOutLocalizations) {
promiseArray.push(getAllCategories(filLoc.localization_id))
}
resolve({ activeLocalization: defaultLocalization, localizations: filledOutLocalizations })
})
})
})
}
initializeBlankState = ( defaultLocalization, localizations ) => {
return new Promise( resolve => {
let activeLocalization = Object.assign(
defaultLocalization,
this.getBlankState(defaultLocalization.localization_id)
)
activeLocalization.product.enable_flg = 1
localizations = localizations.map( l => {
return Object.assign(l, this.getBlankState(l.localization_id))
})
resolve({ activeLocalization, localizations })
})
}
Upvotes: 0
Views: 425
Reputation: 4068
The code does not work in your original version because await
can only be used inside an async
function. The function inside then
has its own scope, which does not relate to the outer one anymore; thus using await
there is invalid.
The second version, in which you put async
inside then
is a violation of return type. From MDN definition of Promise.prototype.then
:
The then() method returns a Promise
and MDN definition of async function
:
The async function declaration defines an asynchronous function, which returns an AsyncFunction object
you can see that those two should not be used together.
Normally, async-await
is used to replace Promise - then - catch
, not for using together. So for your sample function, it should be:
myAsyncFunction = async () => {
const resource = await fetchResource();
if (isValidResource(resource)) {
const anotherResource = await fetchAnotherResource();
...
}
}
And for your function initializeState
, which uses async
:
initializeState = async () => {
const res = await getShopInfo(this.state.shop_id);
if (product_id) {
({ activeLocalization, localizations } = await this.initializeEditState(product_id, defaultLocalization, localizations))
} else {
({ activeLocalization, localizations } = await this.initializeBlankState(defaultLocalization, localizations))
}
}
Upvotes: 2
Reputation: 4630
From my point of view async
inside then(..)
is redundant in your case. Just continue use Promises.In fetchResource().then( res => fetchAnotherResource()).then(res=>{code...})
last code will wait completion of fetchAnotherResource(..)
.
So, your code
.then (async (res) => {
if (product_id) {
({ activeLocalization, localizations } = await this.initializeEditState(product_id, defaultLocalization, localizations))
} else {
({ activeLocalization, localizations } = await this.initializeBlankState(defaultLocalization, localizations))
}
})
can be rewrite like
.then ((res) => product_id?
this.initializeEditState(product_id, defaultLocalization, localizations)):
this.initializeBlankState(defaultLocalization, localizations))
)
.then(({activeLocalization,localizations})=>{.....})
Upvotes: 1