Await does not wait for Promise to finish

472    Asked by AndreaBailey in AWS , Asked on Aug 2, 2021

 In my LWC, I am trying to call an Apex method and wait for it to finish. This is what it comes down to:

import apexMethodA from '@salesforce/apex/SomeControllerClass.apexMethodA'; export default class TradeWindow extends NavigationMixin(LightningElement) { initialJSfunction() { console.log('about to call waitForApexMethodA'); this.waitForApexMethodA(); console.log('finished calling waitForApexMethodA'); // More processing depending on the output of apexMethodA. } async waitForApexMethodA() { console.log('about to call apexMethodA'); try { await apexMethodA(); } catch(error) { console.log(error); } console.log('finished calling apexMethodA'); // Some more processing. } }

To my surprise/horror, this is what the console log shows: about to call waitForApexMethodA about to call apexMethodA finished calling waitForApexMethodA finished calling apexMethodA This is not what I expected and definitely not what I want. I have read lots of documentation about this and I had hoped that await would have the code wait until the Apex method returns with an answer, but apparently that is not how it works. When I read Mozilla's documentation on this, it seems that await does not wait at all: An await splits execution flow, allowing the caller of the async function to resume execution.But in many other places, I read that await and async are the way to go. My code is too complicated to solve this with a chain of .then's, I would like to solve it using await. How can I do that? I tried to wrap the call to waitForApexMethodA in a Promise and await that, but of course, that doesn't work: as soon as await is encountered in waitForApexMethodA, control is returned to the caller. That is not what I want, initialJSfunction should only get control after all of waitForApexMethodA has completely finished.

Answered by Ben PHILLIPS

So it's a bit weird to wait for a promise to resolve your error. The "waiting" happens within that aync function, not your initial js function.

consider this example

      function resolveAfter2Seconds() { return new Promise(resolve => { setTimeout(() => { resolve('2 seconds'); }, 2000); }); } function resolveAfter4Seconds() { return new Promise(resolve => { setTimeout(() => { resolve('4 seconds'); }, 4000); }); } async function asyncCall() { console.log('calling'); const result2 = await resolveAfter4Seconds(); console.log(result2); const result1 = await resolveAfter2Seconds(); console.log(result1); } asyncCall(); console.log('test');

The output of this would be

      > "calling" > "test" > "4 seconds" > "2 seconds"

Note that 4 seconds happens before 2, indicating that the await did in fact work here; however, 'test' was still printed out first. It is essentially the same as stringing promises together as you mentioned, just cleaner.

Your Answer


Parent Categories