Javascript & Promises & Async

I have code that I use to read a config file, save some data, then save the config file and lastly reload the page.

 

The reload has never worked and at times the read config did not occur. After a lot of research I discovered that JavaScript is very asynchronous. Meaning I could never really be guaranteed what code would run when. Most of my issue were due to using Ajax to do all the work, and the GET/PUT/POST being asynchronous.

I rewrote the code many times and finally found a solution. By using the async and await commands I got everything working correctly.

 

Here is the final code.

 

$(document).on('knack-record-create.view_1096', function(event, view, record) {
// Declare variables used
var Prefix = record.field_225_raw;
var Start = record.field_226_raw;
var End = record.field_227_raw;
var Total = record.field_584_raw;

var KnackAppID = "xxx"
var KnackAPIKey = "yyy"


// ******************************************************
// Fucntion to Get the Config data
// ******************************************************
async function GetConfig() {
return new Promise((resolve,reject) => {
$.ajax({
url: "https://api.knack.com/v1/objects/object_80/records/5d4e1092e169b3001096a207/",
type: "GET",
headers: {
"X-Knack-Application-Id": KnackAppID,
"X-Knack-REST-API-Key": KnackAPIKey
},
success: function(data) {
LastBarcode = data.field_784_raw
CurrentPrefix = data.field_785_raw
console.log('Get Config ' + LastBarcode)
resolve(data);
},
error: function(error) {
alert("Get Conifg Error: " + JSON.stringify(data));
Knack.hideSpinner();
reject(error);
}
})
})
}


// ******************************************************
// Fucntion to Save Barcode Data
// ******************************************************
async function PutBarcode() {
return new Promise((resolve,reject) => {
$.ajax({
url: "https://api.knackhq.com/v1/objects/object_10/records/" + record.id,
type: "PUT",
headers: {
"X-Knack-Application-Id": KnackAppID,
"X-Knack-REST-API-Key": KnackAPIKey
},
data: {
field_225: CurrentPrefix,
field_226: LastBarcode + 1,
field_227: LastBarcode + Total
},
success: function(data) {
console.log('Put Barcode ' + LastBarcode)
resolve(data);
},
error: function(data) {
console.log("Save Barcode Error: " + JSON.stringify(data));
Knack.hideSpinner();
reject(error);
}
});
})
}


// ******************************************************
// Fucntion to Save Config Data
// ******************************************************
async function PutConfig() {
return new Promise((resolve,reject) => {
$.ajax({
url: "https://api.knackhq.com/v1/objects/object_35/records/5d4e1092e169b3001096a207/",
type: "PUT",
headers: {
"X-Knack-Application-Id": KnackAppID,
"X-Knack-REST-API-Key": KnackAPIKey
},
data: {
field_784: LastBarcode + Total,
field_785: CurrentPrefix,
},
success: function(data) {
console.log('Put Config ' + LastBarcode)
resolve(data);
},
error: function(error) {
alert("Save Config Error: " + JSON.stringify(data));
Knack.hideSpinner();
reject(error);
}
});
})
}

// ******************************************************
// Main Code to Get Config, Update Barcodes and Save Config
// ******************************************************

const Main = async() => {
await GetConfig()
await PutBarcode()
await PutConfig()
console.log('Reload')
location.reload()
}

Main()

});

 

The last part of wrapping the function within another function was key in getting everything to work.

I'm not sure I fully understand the "why" of how this works, however it does appear do do what I was looking for and is much easier to read than the previous code.

 

Martin

 

 

Add complete option to your Ajax like this:

 $.ajax({
            url: "https://api.knack.com/v1/pages/scene_32/views/view_65/records",
            type: "POST",
            //async: false,
            headers: {'X-Knack-Application-Id':'*******','X-Knack-REST-API-KEY':'*****','content-type':'application/json'},
            data: payload,
            complete:function(data) { 
                  //Refresh Table Content
                  Knack.views["view_65"].model.fetch();
            }, 
            success: function(response) {
                //console.log("Done!");
            }
            });

I'm not a very expert coder either hence many things are a mistery to me, but yet I have solved the same problem using jQuery deferred objects and callbacks. This makes the code a little bit tinier. 

Let's say I have the function myFunc that executes a ajax call. I will return the result of the call itself as such:

function myFunc(){
return $.ajax({ .... });
}

This will return a deferred object which is basically a promise in jQuery custom implementation. I will then manage it with a callback. So in my main code I will have something like:

myFunc().done(function(response){
console.log(response); // this is the response from the ajax call
// do things such a refresh the page here
});

Actually I don't know which is the best way to handle this, but since jQuery is handling promises already why to make additional code?

Davide