0

I have a code like this below (partial code). After the 'step 4' part the code continues and might direct to a new page (unrelated to the result of the saveTokenToUser function. BUT - i need to be sure that the saveTokenToUser and the ajax call in it have completed before the redirect happens.

Currently, I get the following result, despite having the async and await in the function call. I am guessing I just have a wrong syntax?

Step 1, Step 2, Step 4, Step 3

Code

alert('Step 1');
             // save token if app user: 
              if (tokenViaApp !== '' ) {
                  alert('Step 2')
                  var result  =  saveTokenToUser(tokenViaApp);
             }
alert('Step 4')

 async function saveTokenToUser(token) {
        await $.ajax({ 
          type: "GET", 
         // async: false,  // deprecated in jQuery 1.8
          url: "/includes/notifications/", 
          data: {
              t: token
          }, 
          success: function(msg) {  
               localStorage.token_origin = 'app';
               alert('Step 3')
          }
        });
 }

UPDATE:

Following Answer by T.J. Crowder, this is now my code.

JS FIDDLE LINK: https://jsfiddle.net/kneidels/8nsyegz3/

console.log('Step 1')
(tokenViaApp === '' ? Promise.resolve() : saveTokenToUser(tokenViaApp))
    .then(() => {
        // Do the redirect
        console.log('Step 2');
    })
    .catch(error => {
        // Handle/report error
    });
    console.log('Step 4');


async function saveTokenToUser(token) {
        await $.ajax({ 
          type: "GET", 
         // async: false,
          url: "/includes/notifications/", 
          data: {
              t: token
          }, 
          success: function(msg) {  
               localStorage.token_origin = 'app';
               console.log('Step 3')
          }
        });
}

and all I get in the console now is:

Step 1
Step 4 

and the localStorage line in success: function(msg) is not running too ( that obvious, seen as step 3 isnt getting done either.

kneidels
  • 956
  • 6
  • 29
  • 55
  • 2
    Although I can't comment directly on your question, I would highly recommend you use `console.log` instead of `alert`. Alerts stop the processing, which could inadvertently change what your code is doing. Using the `console.log` means that you can still track what's happening in real time without any display interaction – freefaller Jun 06 '19 at 15:57
  • 2
    @freefaller - Indeed -- or better yet, instead of stumbling around in the dark with a `console.log`/`alert` torch, *turn on the lights* using the debugger built into the browser, settings breakpoints, etc. :-) – T.J. Crowder Jun 06 '19 at 16:07

1 Answers1

0

Your code calling saveTokenToUser also has to use await. As it is now, result receives the promise and doesn't wait for that promise to be settled.

You have at least three options:

  1. If that code is in an async function, await the call to saveTokenToUser
  2. If it isn't but you can make it an async function (handling any effect that has on code calling it, and beign sure to handle rejections from it), do that and await the call to saveTokenToUser
  3. Use then and catch on the result of calling saveTokenToUser

#3 could look something like this (I've left out "Step 2" because I assume those are only there for debuggin, and it complicates the below a bit to include it):

console.log("Step 1");
(tokenViaApp === '' ? Promise.resolve() : saveTokenToUser(tokenViaApp))
.then(() => {
    // Do the redirect
    console.log("Step 4");
})
.catch(error => {
    // Handle/report error
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you, Just to clarify - the result of the function does not actually change any of the functionality or logic of the page. it just runs silently. Does this affect the code you suggested above? – kneidels Jun 06 '19 at 18:20
  • @kneidels - Yes, because without `await`, it doesn't wait for completion. Note that your code in the question following this answer *doesn't* follow this answer. `console.log("4")` should be *inside* the `then`, not after it. – T.J. Crowder Jun 07 '19 at 06:05
  • @t-j-crowder , thanks. I setup the code as you suggested in #3, but i dont get a `step 4` written to the console at all now. And the `ajax` call in `saveTokenToUser` isn't even called, according to the log in the Network Tab (thoughi can see an entry into the `saveTokenToUser` function). I have setup a jsfiddle: https://jsfiddle.net/kneidels/8nsyegz3/ – kneidels Jun 07 '19 at 07:54
  • @kneidels - This is why it's important to handle errors, as I show in the above where I say "Handle/report error". Your ajax call is failing: https://jsfiddle.net/tjcrowder/mkbhsde0/1/ Ignoring errors is extremely poor practice and a footgun. – T.J. Crowder Jun 07 '19 at 08:06
  • @t-j-crowder, got it. added extra lines for handling, in the `ajax` call too. But pls see https://jsfiddle.net/kneidels/8nsyegz3/9/ now (console messages) - the page continues to run even without waiting for the ajax call & result. ie, it might reach the redirect a few lines below in the continuation, before the ajax call has been made or completed. this is the whole background to my question and why i need the `await` possibility. Pls see the console messages, you will see what i mean, Thank you – kneidels Jun 07 '19 at 08:30
  • @kneidels - Yes, anything you want to wait **has to go in the `then` handler **. Otherwise, naturally, it gets run right away. If you didn't need to do that, there wouldn't be any point to `then`. You might want to make your whole script block one big `async` IIFE and use `await` to wait for your `async` functions (or functions like `$.ajax` that also return promises). See [my answer here](https://stackoverflow.com/a/46515787/157247) for how to do that. – T.J. Crowder Jun 07 '19 at 08:46
  • ok, so anything that needs to be 'waited for', should go in the `then`. Meaning the ajax call - so that basically means the `saveTokenToUser` function is not needed, correct? (or rather: this cannot even work without doing so)? – kneidels Jun 07 '19 at 08:51
  • 1
    @kneidels - Well, `saveTokenToUser` nicely encapsulates its functionality, so making it its own function makes sense. I would change it slightly to take advantage of `async`/`await` (https://pastebin.com/kvNbfsbF), but I wouldn't remove it. – T.J. Crowder Jun 07 '19 at 08:57