How can I ensure the data in my Journey array is kept up to date without re-building the array on every change

I have a view that shows an array of job objects that are updated by multiple users. How can I ensure that the updates other users make are reflected in this view without users exiting and re-entering? I know that queries refresh "automatically", is there a way to make arrays mimic that behavior?

One way to achieve this is by using the setInterval() method in JavaScript.

Define your xml, e.g.:

    <var name="jobs" type="array:job" />

And write a function that runs at an interval (10000ms, or 10s in this case) in the JS for the view:

function init() {
    // initialize any data here that should be available when the view is shown
    setInterval(function() {
        view.jobs = user.jobs.toArray();
        journey.synchronize();
        journey.forceDigest();
    }, 10000);
}

The above will ensure that the data present on the view remains updated every 10 seconds, whether the user exits and enters the view or not.

I like the idea of using setInterval, but there is two issue around setInterval. 1. When we define a setInterval, you will need to be able to stop it from running when leaving the view for another. Otherwise this will continue to run, even thou we are on other views. This will also create another setInterval when entering the view again.2. setInterval does not take into account the performance of the query, if a query is running longer than 10 seconds (Bad Example I know), another execution has the possibility to execute while the previous is still running.

You can achieve this is by using the setTimeout() method in JavaScript.

Define your xml, e.g.:

    <var name="sync_jobs" type="boolean" />
    <var name="jobs" type="array:job" />

And write a function that runs at an timeout (10000ms, or 10s in this case) in the JS for the view:

function init() {
   // Initialize for the first time
   view.jobs = user.jobs.toArray();

   view.sync_jobs = true;
   syncJobs();
}

function syncJobs() {
  // Only create a timeout if its allowed to run
  if(view.sync_jobs) {
    setTimeout(function() {
        // Sync to get the latest data
        journey.synchronize();

        // And then initialize any data here that should be available when the view is shown
        view.jobs = user.jobs.toArray();
        journey.forceDigest();

        // Call syncJobs to add to the queue again.
        syncJobs();
    }, 10000);
  }
}

function onBack() {
  // Stop execution of syncJobs
  view.sync_jobs = false;
}

The above will ensure that the data present on the view remains updated every +-10 seconds, whether the user exits and enters the view or not.

This also ensures that it stops running once you exit the view and take into account the performance of the query and sync.

6 Likes

Good point re: ensuring the query does not keep running. Does this hold true if the view is discarded, dismissed, replaced or otherwise removed from the stack?

@JasonBordelon yes, it does unfortunately. It actually also blocks the Journey Container from fully discarding the view since references on the view is still kept. So the Garbage Collection cannot collect back the memory used for that view as well.

@AntonVanZyl wouldn’t setInterval() be a better option here? That way you don’t have to retrigger the syncJobs function within itself:
var periodicJobSync;
init() { <br/> <br/> periodicJobSync = self.setInterval(syncJobs, 10000)<br/>}

function syncJobs() {<br/> journey.synchronize();<br/>// And then initialize any data here that should be available when the view is shown <br/>view.jobs = user.jobs.toArray();<br/>journey.forceDigest();<br/>}

function onBack() { <br/> // Stop execution of syncJobs<br/> self.clearInterval(periodicJobSync);<br/>}

@AntonVanZyl wouldn’t setInterval() be a better option here? That way you don’t have to retrigger the syncJobs function within itself: var periodicJobSync; function init() { periodicJobSync = self.setInterval(syncJobs, 10000); } function syncJobs() { journey.synchronize(); // And then initialize any data here that should be available when the view is shown view.jobs = user.jobs.toArray(); journey.forceDigest(); } function onBack() { // Stop execution of syncJobs self.clearInterval(periodicJobSync); } (Sorry for the bad formatting)

@HeinduToit setInterval does not take into account the performance of the query, if a query is running longer than 10 seconds (Bad Example I know), another execution has the possibility to execute while the previous is still running. If an exception is thrown in setInterval, it would not stop the execution of this as well, up to you to decide if this okay in your case. It also would not stop if you updated the app while in development and you lose reference to the setInterval.Neither one is bad, you just need to be more specific with setInterval than setTimeout to ensure no issues arise.

If you combine this with on-navigate it will mitigate the issue regarding garbage collection. You can add a new variable to your view, query_refresh_id.

Then call view.query_refresh_id = setTimeout(function () { in init and resume and call clearInterval(view.query_refresh_id) in your on-navigate function.

1 Like