Forum Discussion

_anomDiebolt_'s avatar
_anomDiebolt_
Qrew Elite
8 years ago

What is the Async / Await Technique?

What is the Async / Await Technique?
  • I am glad you asked as I have been waiting a long year to reveal this new technique. I was denied the opportunity to present this talk at last year's Empower conference but I can wait no longer (there is a plan you know and we have to keep on schedule).

    In a nutshell the Async / Await Technique is the a simplified way of making asynchronous AJAX calls to QuickBase but to have the code appear synchronous. That explanation may not make much sense now but suffice it to say that using the new async / await feature in JavaScript allows you to write arbitrary complex sequences of AJAX calls without using callbacks or chaining promises together using then() methods. Perhaps an example will clear up any confusion.

    Let's say we have an application with two tables (Table #1 and Table #2) and we want a script  that will purge Table #2 of all records and then copy all records returned from a query of Table #1 into Table #2. But since we want to emphasize that this technique can deal with any number of API calls we will purposely copy the records individually using multiple calls to API_AddRecord rather than using one call to API_ImportFromCSV.

    So visit the following application and paste the code below into the console:

    Async / Await
    https://haversineconsulting.quickbase.com/db/bm3mnhpzq

    Pastie Database
    https://haversineconsulting.quickbase.com/db/bgcwm2m4g?a=dr&rid=598

    If you look closely at the code you will see we wrote a function named process() that was called like this:
    process(dbidTable1, qid1, dbidTable2);
    However, process() was not a normal function as it has the new keyword async in front of its definition:
    async function process(dbid1, qid1, dbid2) {
      //step 1 - Purge all records in Table 2
      //step 2 - Query all records in Table 1
      //step 3 - Loop over all records from step 2 and add record to Table 2
    }
    What this async keyword does is allow the function to pause occasionally at points in the code where an await keyword is used to indicate that we are waiting for the promise associated with an AJAX call to complete and return its result. As a consequence you will see several instances of await in the script similar to the following:
    //step 1 - Purge all records in Table 2 var xml1 = await Promise.resolve(
      $.get(dbid2, {
        act: "API_PurgeRecords",
        qid: "1"
      })
    );
    Note there are no callbacks, then() methods or unnecessary indentation in the code. In fact, the code appears to read similar to synchronous code with one line of code following another in linear execution sequence.

    I will have more to say about this technique in subsequent posts but this Async / Await Technique blows the doors off all prior asynchronous coding paradigms and it makes scripting QuickBase very easy.
    • _anomDiebolt_'s avatar
      _anomDiebolt_
      Qrew Elite
      Yes the code is shorter but the big benefit is that the code appears linear or synchronous even though it is actually asynchronous. If you ran a loop of 100 asynchronous AJAX calls without using async / await your browser would crawl to a halt and throw an error waiting for an available socket.

      This Async / Await Technique revolutionizes scripting QuickBase.

      I declare a holiday - everybody slack off and celebrate today.
    • _anomDiebolt_'s avatar
      _anomDiebolt_
      Qrew Elite
      I wanted to add some notes to the original post when I had a minute so here goes:

      Notes:

      (1) There are two types of promises being used in this code. All jQuery AJAX methods return promises but these are jQuery Promises not native JavaScript Promises. jQuery Promises came first before native JavaScript Promises were adopted by browsers. Luckily there is some compact notation to convert a jQuery Promises into a native JavaScript Promise. All you have to do is wrap the jQuery promise in a call to Promise.resolve() like so:

      Promise.resolve(
        $.get(dbid2, {
          act: "API_PurgeRecords",
          qid: "1"
        })
      )

      (2) Only native JavaScript Promises can be used with Async / Await.

      (3) You may be wondering why bother with jQuery at all - its is 10 years old and there are more than adequate selectros and AJAX methods native to the browsers today. There are three reasons:

      (a) QuickBase users are more familiar with jQuery than advanced JavaScript techniques and jQuery is already being used by QuickBase so why not continue to use it for the time being.

      (b) Although the Fetch API is a better way to make AJAX calls than jQuery it lacks the equivalent of $.ajaxSetup({data: {apptoken: apptoken}}) to attach default parameters to all AJAX calls. Overall you code will be shorter using $.ajaxSetup() which is an important consideration when injecting code into a QuickBase page/

      (c) Similar to (b) the Fetch API does not accept a data object but requires you to use the more verbose FormData objects for the body payload. Again the goal of shorter code works in favor of using jQuery for AJAX calls in the current environment.

      So the net result is that given the unique environment of QuickBase the best approach is to continue to use jQuery AJAX methods but wrap them in the newer Promise.resolve() method which can be used with Async / Await.

      This is sort of a strange arrangement but it results in the most compact code while still taking advantage of advanced JavaScript features and not require the loading of any additional libraries.