Priority of execution?

Is there a concept of Priority of Execution in Appgyver?

The situation is: My app has couple of background processes running to fetch data. Some user actions also create other background processes.
The problem is: Those background processes seem to have equal execution priority to the app UI events. It makes UI slow in responding to click events.

Is there a way to give top execution priority to any UI events?, so the app can be more responsive?

Thanks for the tips.

1 Like

You can kind of engineer this yourself.

Create some page variable in each flow. Set their state depending on if they are running or not.

Detect what they all are and stop the lower priory flows from executing if the other ones are in progress. Just put them on a timer loop. You could do this at more than one place in the flow if desired.

1 Like

Yes I tried that as well and it sort of works, but it solves a part of the problem only. In cases where the data process: 1) checks the priority variable, then 2) decides to run, and it takes say 5 seconds before it will finish and come back to look at the priority variable again. But in the middle of that 5 seconds, if the UI is clicked, then it lags a lot.
The problem gets worse if there are multiple processes like that fighting for a run slot.

1 Like

Very relevant discussion. Very well put.

I also experiment unresponsiveness in my app due to retrieving data, populating data variables and rendering lists.

1 Like

I have a load of wait loops in mine to make the UX ok. I do most of my data loading on startup too.

1 Like

I had implemented a lazy loading loop in the global canvas app page; I’m loading hundreds of database records including high resolution images in a loop;

This way the UI is responsive to users interactions; the idea being that the end users should be able to use the app as soon it is launched and then freely navigate between widgets and pages…

PS. The data load and processing happens asynchronously in the background as soon as the app is launched.
I have decided to load metadata and the content asynchronously to make sure the user experience is smooth

1 Like

Nice solution indeed! Looking at the flow, it seems that the async load happens inside the JS functions?

Thanks @Steven_Nguyen ; Indeed; for instance this is how I load images one by one…

// https://stackoverflow.com/questions/3774622/how-to-base64-encode-inside-of-javascript
// React Native atob() / btoa() not working without remote JS debugging - Stack Overflow
// https://stackoverflow.com/a/42833475

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const myBase64 = {
  btoa: (input = '')  => {
    let str = input;
    let output = '';

    for (let block = 0, charCode, i = 0, map = chars;
    str.charAt(i | 0) || (map = '=', i % 1);
    output += map.charAt(63 & block >> 8 - i % 1 * 8)) {

      charCode = str.charCodeAt(i += 3/4);

      if (charCode > 0xFF) {
        throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
      }

      block = block << 8 | charCode;
    }

    return output;
  },

  atob: (input = '') => {
    let str = input.replace(/=+$/, '');
    let output = '';

    if (str.length % 4 == 1) {
      throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
    }
    for (let bc = 0, bs = 0, buffer, i = 0;
      buffer = str.charAt(i++);

      ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
        bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
    ) {
      buffer = chars.indexOf(buffer);
    }

    return output;
  }
};

var array  = inputs.input1
var arrURL = inputs.input2;
var i = inputs.input3;

{
  array[i].ImageUrl; 
  var imageURL  = 'https://<path>' + array[i].ImageUrl; 
  //console.log(imageURL);
  
  try {
    const response = await fetch(imageURL);
    const json = await response.json();
  
    //return { result: json.data};  
    const bytes = myBase64.atob(json.image)
      .split('')
      .map(c => c.charCodeAt(0));
    console.log('bytes: ', bytes.length)
    const blob = new Blob([ new Uint8Array(bytes) ], { type: 'image/jpeg' });

    //console.log('blob: ', blob)
    
    const url = (URL || webkitURL).createObjectURL(blob);
    console.log(url)
    arrURL[i] = url;


  } catch (err) {
    const error = {
      code: 'unknownError',
      message: 'Something went wrong with blob.',
      rawError: err,
    }
    
    console.log(error)
    return [1, { error }]
  }
 }

 return { result: arrURL };
2 Likes

Yes this was one of the first signs I saw too. I ended up ditching the built in data connectors and wrote everything to local firebaseIndexDb, then ended up writing my own code to handle communication with firebase. But you can also set events to trigger based only on the data written to indexDB so that the user gets instant feedback and your app can write to firebase using the on change events from global page. But either way the custim fetch API in a javascript node works way better.