1

N.B. BEFORE DELETING AS DUPLICATE: I realise that similar questions have been asked many times before, however I have spend several hours trying to implement this using other people's responses, most recently the response from noseratio in this thread Proper way to wait for one function to finish before continuing? and have had no success.


I have a nodeJS server which successfully returns data when my function f1 requests it, and another function f2 which calls f1 and then is meant to do something with the output of this async function. I am trying to do this with async/await syntax and an additional promise in f2, as shown below.

async function f1(){
   try{
       let response = await fetch('MY SERVER URL');
       let data = await response.json();
       return await data;
   }
   catch(e) {
       alert(e);
   }
};


function f2() {
    var promise = f1();
    promise.then(function(result) {
        JSONdata = promise.markers;
        console.log("JSON read into f2");
    })    

    console.log(JSONdata);

and then f2 goes on to do other stuff...

However the issue is that I am experiencing race conditions with the result of f1 not being returned in time to be able to do anything with it, and so the variables are undefined.

Any help on how to mitigate this would be appreciated, thanks.

B_D_E
  • 109
  • 2
  • 10
  • 3
    Triple `await` should error in `f1`, you should not need the last `await`. Also this isn't a race condition, everything that depends on the promise being resolved should go in the `then` statement, or you can just use another `async` function. – Aplet123 Mar 31 '20 at 19:30
  • 1
    @Aplet123 I mostly agree, however the last `await` shouldn't error. It's not needed, but awaiting a non-promise returns the value itself. `n = await 1` will simply assign `1` to `n`. – 3limin4t0r Mar 31 '20 at 19:36
  • Huh, that's strange. I've just always made it a habit to not await non-promises. – Aplet123 Mar 31 '20 at 19:39
  • 1
    um, `console.log(JSONdata);` should be inside the then...... – epascarello Mar 31 '20 at 19:42
  • 1
    Please post the exact code of "*and then f2 goes on to do other stuff...*". In general, there's no way to avoid putting that stuff inside the `then` callback or after an `await`, and to have `f2` return a promise as well. That's what f1 being asynchronous means. – Bergi Mar 31 '20 at 19:51

3 Answers3

2

Stick to this pattern.

async func1() { 
  console.log('this is async function')
  return JSON.parse(await fetch(options))
}

func2 () { 
   console.log('this is not async function')
 }

        if(await func1()){
            func2()
        }

And you've got too much awaits in function 1. Await only for return of promise. And you shouldn't confuse yourself at this level with mixing '.then' and 'await' syntax. Try to stick to one pattern, then explore another one. Then mix it.

Ivan Kolyhalov
  • 902
  • 11
  • 16
2

Something like this should work:

async function f1() {
   try {
       const response = await fetch('MY SERVER URL')
       return await response.json()
   } catch(e) {
       console.error(e)
   }
}

async function f2() {
    const { markers } = await f1()
    console.log(`Result supplied to 'f2': ${markers}`)
}

In your code, the await in return await data is redundant because data is not a promise; also, f2 appears incomplete.

Note that although, in general, return await... is unnecessary in async functions (and considered bad form, even though it is harmless), if you want a surrounding try...catch to catch promise rejections, then return await... is necessary. See here.

Ben Aston
  • 53,718
  • 65
  • 205
  • 331
  • 1
    Actually, a `try` block is the only place where the `await` is *not* redundant. (What was redundant is the second `await` on `data`) – Bergi Mar 31 '20 at 20:02
  • Oh, ok. So to make use of the catch in `f1`, `return await` is valid? – Ben Aston Mar 31 '20 at 20:04
0

You should either move the logic that makes use of the f1 result inside the then callback.

function f2() {
    var promise = f1();
    promise.then(function(result) {
        var JSONdata = result.markers;
        console.log("JSON read into f2");

        console.log(JSONdata);
    });
}

Or change f2 to an async function so you can await the return value.

async function f2() {
    var result = await f1();
    var JSONdata = result.markers;
    console.log("JSON read into f2");

    console.log(JSONdata);
}

If you haven't already, check out the MDN Using Promises guide, which explains them pretty thorough. When you have an understanding of how promises work async/await will also become a lot more easy to understand.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • Perfect, thanks a lot. I'll have a read of those MDN docs again - I realise now that I'd got mixed up with multiple variations of the syntax & syntactic sugaring. – B_D_E Mar 31 '20 at 21:19