Skip navigation
All Places > AppStudio for ArcGIS > Blog > 2019 > June
2019

The AppStudio team is hard at work on the next version of AppStudio for ArcGIS (version 4.0). As always there will be technical updates to the software, but with this new version there will also come some significant changes to how we license the software.

 

More details about the new technical features and capabilities coming with AppStudio 4.0 are detailed in this blog post, but here is an overview of the highlights.

  • New 3D Scene Viewer template
  • AppStudio extension for Visual Studio Code (open VS Code from AppStudio, write QML)
  • Support for opening a permission dialog while app is running
  • Preview file before sharing
  • Change language while app is running
  • Updates to JavaScript environment (ECMAScript 7)

If you want access to the AppStudio 4.0 beta visit the AppStudio for ArcGIS Early Adopter Community.

 

Licensing Changes

 

AppStudio is a powerful suite of tools that provides our users an easy to use, yet extremely robust cross-platform app development experience. We want more ArcGIS users to experience the full power of AppStudio, and have access to more templates, layouts, samples, and tools. To give access to more of what AppStudio has to offer, we have decided to make some changes to the license levels.

 

Name Change

First things first, we are changing the name of the licensing levels

 

Original NameNew Name
AppStudio for ArcGIS BasicAppStudio for ArcGIS
AppStudio for ArcGIS StandardAppStudio for ArcGIS Developer Edition

 

Just as before, every ArcGIS organization member with a user type of Creator or GIS Professional will have access to AppStudio for ArcGIS (we’ve dropped “Basic” from the name). If you have an AppStudio for ArcGIS Standard license it will be renamed to AppStudio for ArcGIS Developer Edition. We are also working on making an easier experience to purchase and provision an AppStudio Developer Edition license to the ArcGIS organization of your choice.

 

 

What comes with an AppStudio for ArcGIS license?

 

Previously, the AppStudio Basic license lets you create a native app from one of three templates on appstudio.arcgis.com. This online template experience offered minimal configuration options and required that maps and data be public. At version 4.0 all AppStudio for ArcGIS licenses now includes the AppStudio Desktop application. AppStudio Desktop lets you configure an app from a template, build an app from a layout, or add functionality to an app using code from one of our 70+ live samples. Speaking of code... also included is the ability to write custom code for your app using Qt Creator (installed with desktop) or Microsoft Visual Studio Code (using a new AppStudio extension).

 

After you have created an app using AppStudio Desktop you can upload it to your ArcGIS organization and share it with others in your org using AppStudio Player. An AppStudio app stored in ArcGIS Online is just another item in your organization. And just as you share data, maps, and web apps with others, you can share your AppStudio apps and then run the app using AppStudio Player (more about AppStudio Player below).

 

Note: The app building experience on appstudio.arcgis.com will be retired on August 15th, 2019, see the Q&A below for more information.

 

What comes with an AppStudio for ArcGIS Developer Edition license?

 

The Developer Edition license adds a few key components for more advanced developers or those who want to distribute their apps as a standalone installed app via a public app store or an enterprise deployment. The Developer Edition includes a set of Enterprise templates such as Survey123, AuGeo, and AppStudio Player. Access to the AppStudio cloud Make service is also included with the Developer Edition so you can generate app installation files for iOS, Android, Windows, Mac, and Linux.

 

This table highlights the capabilities of AppStudio editions at version 4.0:

AppStudio
for ArcGIS
AppStudio
Developer Edition
Download and use AppStudio DesktopXX
Convert your ArcGIS web maps into mobile appsXX
Build apps with no coding, using configurable app templatesXX
Extend apps built using the configurable app templatesXX
Create custom apps using your developer skillsXX
Share apps within your ArcGIS organization using AppStudio PlayerXX
Use Cloud Make to build install executables
(Android, iOS, Windows, OS X Linux)
X
Publish to the Apple and Google Play app storesX
Use Mobile Device Management (MDM) systems to share in an EnterpriseX
Access to AppStudio enterprise app templates
(Survey123, QuickCapture, AuGeo, more...)
X
In the future - Create add-ins for Survey123 for ArcGISX

 

We are excited about these new changes to AppStudio and the opportunity to share more of the great tools in AppStudio with a larger audience. We understand that these changes may be disruptive for some of our existing users who have been using the web experience to build apps. Please reach out to us (appstudiofeedback@esri.com) so we can better help you through this license transition.

 

Below is a Q&A to help with some of the common questions we think people might have. If you have other questions, please leave them in the comments section below.

 

Thank You – The AppStudio team


Q & A


What will happen to the app building experience on appstudio.arcgis.com website?

The template based app building tools on appstudio.arcgis.com will be shutdown August 15th, 2019 with the release of AppStudio 4.0. Going forward you will use the tools in AppStudio Desktop to configure an app based on one of the standard templates (Map Viewer, Map Tour, Quick Report). AppStudio Desktop offers many more settings for these templates, so you have more control configuring the look and feel of your app... without writing any code. Some of the settings you can configure in AppStudio desktop include the app color, text color, custom fonts, feedback email, offline map package, and more.

If you have already created apps using the website tools those apps will not go away, you can download and further customize those apps using AppStudio Desktop.


What AppStudio license level has access to generate a build? (access to cloud Make)

A significant change in the licensing is that to generate a standalone install build (suitable for submitting to the app stores) for an app will require an AppStudio Developer Edition license.
Those users who have created apps from the website experience using an AppStudio Basic license will no longer have access to generate a standalone build of their app after August 15th, 2019.


How do I share my app with others using AppStudio Player for ArcGIS?

AppStudio for ArcGIS Player is an amazing tool that can transform how you distribute apps in your organization. Using AppStudio Player is like having a private app store, which you control. You can determine who has access to what apps in your organization and when they get updated.

Here how it works:
1. Create an app using AppStudio Desktop
2. Using AppStudio Desktop upload your app to ArcGIS Online or Enterprise
3. In your portal set the sharing property to share your app with others in your ArcGIS organization. Share it with a group of users, the entire organization, or even the public.
4. The end user of the app downloads AppStudio Player onto their device from the app stores or from the AppStudio website.
5. They login using their username/password for their ArcGIS organization.
6. Next, they download the shared app to the device
7. Now they can run the app as a native application right within AppStudio Player

We are excited to announce the release of AppStudio for ArcGIS 4.0 Beta.  Downloads are available through the Early Adopter Community. We encourage you to participate in the beta program to try out new features, enhancements and report bugs. Your feedback will greatly help us improve AppStudio and deliver a stable, high-performance product to everyone.

 

 

New licensing model

We want more ArcGIS users to experience the full power of AppStudio, and have access to more templates, layouts, samples, and tools. To give access to more of what AppStudio has to offer, we have decided to make some changes to the license levels with the AppStudio 4.0 release.  The changes include:

  • License level name change
    • AppStudio for ArcGIS
    • AppStudio for ArcGIS Developer Edition
  • AppStudio by default now includes the ability to make changes to any app or sample or template and upload to the Player (Previously this required a full standard license).
  • Retiring web-based app building tools on appstudio.arcgis.com
  • Cloud Make service will only be included with AppStudio Developer Edition

 

We are excited about these new changes to AppStudio and the opportunity to share more of the great tools in AppStudio with a larger audience.  We understand that these changes will impact the workflow of some of our existing AppStudio users. Please read this blog post for full details on the new licensing changes:
BLOG: Licensing changes coming in AppStudio for ArcGIS 4.0

 

New 3D Scene Viewer template

We released the 3D Scene Viewer as a sample app in the last release – thank you for all of the great feedback and suggestions. With this release, the 3D Scene Viewer has received many new features, enhancements, UI updates, and more customization options. We are excited to publish it as a configurable template app. Please try out this new template app and let us know what do you want to see in the future release in the comment below or email appstudiofeedback@esri.com.  

 

Notice that Support for Mobile Scene Packages coming soon

 

 

   3D Scene Viewer template

 

AppStudio for ArcGIS extension for Visual Studio Code

Visual Studio Code, an alternative code editor to Qt Creator, has been supported since the last release. We have continued our work on Visual Studio Code integration and have simplified the process of opening the AppStudio project in Visual Studio Code.  A new Editor session has been added in AppStudio Preferences, allowing you to choose Qt Creator or Visual Studio Code as your default code editor. Once your default is set, clicking on the Edit button in the side panel will open your AppStudio in the desired code editor. Please refer to this documentation for using the AppStudio for ArcGIS extension for Visual Studio Code.

 

 

 

Support for opening permission dialog prompt

We are excited to introduce the new Permission singleton and PermissionDialog QML component in the AppFramework Platforms plugin. The Permission singleton can query the permission status. The PermissionDialog component provides the ability to open a dialog prompt to ask for the camera, microphone, storage (Android), location, or background location permission on mobile devices. It can also open the device settings if the user declines the permission prompt.

Note: API references of these new features and enhancements are available in the Qt Creator Help documentation included with the AppStudio Desktop 4.0 (Beta) install.    

 

                                                                           Permission Dialog Sample

 

Notice that a Permission Dialog sample app is available in AppStudio Desktop. You can download the sample app here: AppStudio Desktop 4.0 beta > New App > search for Permission Dialog.

 

Support for previewing and sharing files

We have been actively listening to feedback and suggestions from the community and are happy to announce support for one of the most requested features - previewing and sharing files. We have enhanced the AppFramework clipboard.share(fileURL) method to open an appropriate user interface for a specific file (PDF, image, audio, video, and more), allowing you to preview and share the file.

 

 

                                                                      Share text, URL, or file sample

 

 

Support for changing languages when the app is running

Previously, the language of a localized AppStudio app would be based on the device language. With this release, you can now change app language inside of the app without changing the device language. This is huge as now you can also test your apps without changing phone OS locale and also have the ability to provide the option in UI to switch between languages.

 

Internationalization sample

 

 

Others:

  • Upgraded Qt to version 5.12.3
  • We have ended support for creating Android x86 apps.
  • AppStudio 4.0 will be the last version to support Android 4.4.

 

Getting Started

The beta program is open to anyone – join the Early Adopter Community today to gain access to the latest versions of AppStudio 4.0 Beta.

 

  • AppStudio Desktop- You can download the beta version of AppStudio Desktop 4.0 here.
  • AppStudio Player (iOS)- AppStudio Player 4.0 (Beta) is available via Apple's TestFlight. Please click on this link to download.
  • AppStudio Player (Android) - AppStudio Player 4.0 (Beta) is available via the Android Beta Program. Please go to this link to download.

 

You are now all set to start testing the AppStudio 4.0 Beta!

 

Feedback

Your feedback is much appreciated and will help us to improve the final release of AppStudio for ArcGIS 4.0. For bugs or other issues you may find, please submit a bug report or join the beta forum to provide feedback. You can also send us an email at appstudiofeedback@esri.com.

 

The AppStudio for ArcGIS 4.0 final release is scheduled for late August.  We want to thank everyone who contributes to this release in advance, and we wish you happy testing!

 

Become an AppStudio for ArcGIS developer! Watch this video on how to sign up for a free trial.

 

Follow us on Twitter @AppStudioArcGIS to keep up-to-date on the latest information and let us know about your apps built using AppStudio to be featured in the AppStudio Showcase.

 

The AppStudio team periodically hosts workshops and webinars; please click on this link to leave your email if you are interested in information regarding AppStudio events.

SQuan-esristaff

Sorting QML ListModels

Posted by SQuan-esristaff Employee Jun 19, 2019

1. Introduction

 

 

This blog post discusses sorting the QML ListModel. It's one of my favourite problems to solve. The blog also talks about a Sorting Cities sample app. That sample app implements and demonstrates the QML ListModel sort. The rest of the blog explains how the function works.

 

 

2. Sorting Cities sample app

 

 

 

 

The Sorting Cities sample app is an AppStudio 3.3 app. It comes with five U.S. cities. The user can sort them by city name or by distance to ESRI. The sort order can be either ascending or descending.

 

Item {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 10 * AppFramework.displayScaleFactor

        spacing: 10 * AppFramework.displayScaleFactor

        ListView {
            id: listView
            Layout.fillWidth: true
            Layout.fillHeight: true
            model: ListModel {
                id: listModel
                Component.onCompleted: {
                    add( "Hawaii", 21.289373, -157.917480 )
                    add( "Los Angeles", 34.052235, -118.243683 )
                    add( "New York City", 40.730610, -73.935242 )
                    add( "Redlands", 34.0555700, -117.1825400 )
                    add( "Seattle", 47.608013, -122.335167 )
                }
                function add(city, lon, lat) {
                    const esri = QtPositioning.coordinate( 34.0572522, -117.1945814 )
                    const coord = QtPositioning.coordinate( lon, lat )
                    const distance = coord.distanceTo( esri )
                    append( { city, coord, distance } )
                }
            }

            delegate: ItemDelegate {
                text: `${city} ${(distance / 1000).toFixed(2)} km`
            }
        }

        Button {
            text: qsTr("  City  ")
            onClicked: listModelSort( listModel,
                                      (a, b) => a.city.localeCompare(b.city) )
        }

        Button {
            text: qsTr("  City (Desc)  ")
            onClicked: listModelSort( listModel,
                                      (a, b) => - a.city.localeCompare(b.city) )
        }

        Button {
            text: qsTr("  Distance to Esri  ")
            onClicked: listModelSort( listModel,
                                      (a, b) => (a.distance - b.distance) )
        }

        Button {
            text: qsTr("  Distance to Esri (Desc)  ")
            onClicked: listModelSort( listModel,
                                      (a, b) => - (a.distance - b.distance) )
        }
    }

    function listModelSort(listModel, compareFunction) {
        let indexes = [ ...Array(listModel.count).keys() ]
        indexes.sort( (a, b) => compareFunction( listModel.get(a), listModel.get(b) ) )
        let sorted = 0
        while ( sorted < indexes.length && sorted === indexes[sorted] ) sorted++
        if ( sorted === indexes.length ) return
        for ( let i = sorted; i < indexes.length; i++ ) {
            listModel.move( indexes[i], listModel.count - 1, 1 )
            listModel.insert( indexes[i], { } )
        }
        listModel.remove( sorted, indexes.length - sorted )
    }
}

View the full SortingCities.qml on Github Gist.

 

 

3. ListModel vs Array

 

 

If you compare the ListModel QML Type with the Javascript Array type, you'll find that Array has better methods. In particular, Array has a sort method whilst ListModel does not.

 

When you assign an Array to a QML visual component, e.g. ListView, the Array behaves like a scalar value. If you were to push new records onto the Array the ListView will not update. There is no property binding between pushes to the Array and the ListView. To refresh the ListView you need to reassign the Array every time the Array changes. This will cause the ListView to repaint. This could lead to bad user experience. For instance, I may be writing an application that collates results from an online search. The results may arrive through a series of NetworkRequests to REST API end points. Each update will cause the ListView to repaint and scroll back to the top. This will be particularly annoying to the user if the user was already reading and scrolling through the results.

 

The experience is different with ListModels. When you assign a ListModel to a ListView you don't need to assign it again. When you append new records to the ListModel, the ListView will receive sufficient change notification and will automatically update to reflect that new records have arrived. If the ListModel were to change whilst the user was reading and scrolling through the ListView, the current scrolled position and the selected item will be unchanged. The user would not experience any negative user experience with the ListView.

 

In short, for good user experience, we prefer ListModels over Arrays.

 

 

4. Compare Functions as Arrow Functions

 

 

Array sort (and QML ListModel sort) requires a compare function. A compare function takes any two elements from the Array (or ListModel) and returns an integer. It can be negative, zero or positive. For example, if one wanted to compare any two numbers, one could write the following compare function:

 

function compareNumbers( a, b ) {
    return a - b
}

 

If a was greater than b then the function would return a positive number.

If a was the same as b then the function would return zero.

If a was less than b then the function would return a negative number.

 

Then, you would use the compare function as follows:

 

function compareNumbers( a, b ) {
    return a - b
}

let numbers = [ 5, 2, 11, 3, 7 ]
numbers.sort( compareNumbers )
console.log( numbers ) // [ 2, 3, 5, 7, 11 ]

 

If your compare function is simple, you can inline it with your sort call, i.e.

 

let numbers = [ 5, 2, 11, 3, 7 ]
numbers.sort( function compareNumbers( a, b ) { return a - b } )
console.log( numbers ) // [ 2, 3, 5, 7, 11 ]

 

In AppStudio 3.3, Qt 5.12.1 you can use the ECMAScript 6 arrow function syntax, i.e.

 

let numbers = [ 5, 2, 11, 3, 7 ]
numbers.sort( (a,b) => a - b )
console.log( numbers ) // [ 2, 3, 5, 7, 11 ]

 

You'll see the arrow function syntax allows us to omit the 'function' keyword, the function's name and the 'return' keyword. We make this choice if we believe such a choice improves our code readability and maintainability.


In the Sorting Cities sample app, I used the arrow function syntax for all 4 buttons, e.g.

 

Button {
    text: qsTr("  City  ")
    onClicked: listModelSort( citiesListModel,
                              (a, b) => a.city.localeCompare(b.city) )
}

 

 

5. Implementing listModelSort

 

 

There are plentiful sorting algorithms out there. Whilst we can implement one in QML / Javascript, I don't think this is a good idea. We would be implementing a sort algorithm that we would required to maintain. One of the best algorithms out there, Quicksort, is complex to transcribe correctly. Also such an implementation would be executing entirely in Javascript and will not be leveraging much from native code.


Instead, I wanted to leverage from Array sort's implementation. In a nutshell, the algorithm would be:

 

  1. Copy items from the QML ListModel to an Array
  2. Perform an Array sort
  3. Copy the resultant items from the sorted Array back to the QML ListModel

 

Turns out, we can optimized the above technique by not copying the items but linking to them via an index. i.e. The Array would be a set of integer indexes and we just be traversing it as a on the fly lookup into the QML ListModel.

 

Let's begin by creating an indexes Array the exact same size as our ListModel with numbers ranging from 0 to N - 1:

 

let indexes = [ ...Array(listModel.count).keys() ]

 

Then, we use Array's sort method to reorder the indexes Array. We use an arrow function to pick any two entries from the QML ListModel and feed them to the user supplied compare function:

 

indexes.sort( (a, b) => compareFunction( listModel.get(a), listModel.get(b) ) )

 

This reorders the indexes Array. We can now use this sorted Array to traverse the ListModel in sorted order.

 

Whilst we can stop here, I wanted to go further and use theses indexes to rearrange the QML ListModel.

 

for ( let i = 0; i < indexes.length; i++ ) {
    listModel.move( indexes[i], listModel.count - 1, 1 )
    listModel.insert( indexes[i], { } )
}
listModel.remove( 0, indexes.length )

 

The above loop iterates through the items in the ListModel in sorted order. For each item, we move it to the end of the ListModel in sorted order. Once all the items have been moved, we delete the empty holes left behind by the move. It's a heavy handed approach. In my final version I made an optimization that reduces the amount moving and deletion.

 

 

The animation above helps you visualize sorting the cities based on their distance to ESRI. We see it quickly identifies the sort order as Redlands, Los Angeles, Seattle, New York City and Hawaii. The records are tagged by an index 0...4. Next, the sorted records are moved, one by one, to the end, then the sorted records are moved back to the top deleting the temporary empty holes.

 

 

6. Closing Remarks

 

 

For good user interfaces I recommend storing your content in ListModels instead of Arrays. This is so that updates to the content will not interrupt the user experience.


Whenever you can, leverage from an existing implementation (e.g. Array sort) rather than implement your own. You minimize your coding effort and future maintenance efforts.

 

The ECMAScript 6 arrow function syntax can help you express simple sorting compare functions. Otherwise, if they're complex, then, then you should use a named compare function.

 

 

7. References

 

 

 

Send us your feedback to appstudiofeedback@esri.com

 

Become an AppStudio for ArcGIS developer! Watch this video on how to sign up for a free trial.

 

Follow us on Twitter @AppStudioArcGIS to keep up-to-date on the latest information and let us know about your creations built using AppStudio to be featured in the AppStudio Showcase.

 

The AppStudio team periodically hosts workshops and webinars; please click on this link to leave your email if you are interested in information regarding AppStudio events.

1. Javascript Promise

 

 

AppStudio 3.3, Qt 5.12.1 and ECMAScript 7 (which includes ECMAScript 6) introduced native Javascript Promises.

 

This blog is to give you a brief overview of what Promises are and how they matter to AppStudio and QML. This blog isn't a comprehensive guide to Promises. There already is a lot of content on the internet. I recommend you seek them out.

 

Promises is a Javascript coding pattern for working with asynchronous tasks.

 

AppStudio (and QML) has signals and slots for working with asynchronous tasks. If your applications are written and easy to maintain then you probably don't need to look into Promises right now.

 

However, if your applications are complex with business logic spanning over a complex sequence of signals and slots then buying into Promises may be the key to reduce code complexity.

 

Note that the ArcGIS.AppFramework.Promises module is being deprecated in favour of native Javascript Promises. We advise discontinuing using ArcGIS.AppFramework.Promises module and begin removing them from your existing AppStudio apps.

 

 

2. Promise Download Sample

 

 

Let's look at an AppStudio app that simulates downloading content from the internet.

 

 

When the Button is clicked, we simulate 3 concurrent downloads. The downloads will finish 0-1000ms after the Button's onClicked handler has finished. Each download's success/failure will be independent of each other.

 

    Button {
      text: qsTr("Test Promise timeout")
      onClicked: {
        download( "GET", "https://community.esri.com/groups/appstudio" )
          .then( (message) => { console.log( message ) } )
          .catch( (error) => { console.log( error ) } )
        download( "GET", "https://appstudio.arcgis.com" )
          .then( (message) => { console.log( message ) } )
          .catch( (error) => { console.log( error ) } )
        download( "GET", "https://community.esri.com/groups/survey123" )
          .then( (message) => { console.log( message ) } )
          .catch( (error) => { console.log( error ) } )
      }
    }

    function download( method, url ) {
      return new Promise( (resolve, reject) => {
        if (Math.random() < 0.30)
          setTimeout( reject, Math.floor(1000 * Math.random()), `Download failure ${url}` )
        else
          setTimeout( resolve, Math.floor(1000 * Math.random()), `Download success ${url}` )
      } )
    }

View the full PromiseTimeout.qml on GitHub Gist.

 

Some key features of Promises:

 

  • The task begins as soon as new Promise() { ... } is called.
  • The task is defined as (resolve, reject) => { /* body */ } where either resolve(data) or reject(error) will be called when the task completes.
  • Use then() method to supply your success handler.
  • Use catch() method to supply your failure handler.

 

You may be thinking "This looking confusing" and "Do I need this?". I ask you to consider this: the Button's onClick handler fully describes 3 download tasks and what to do when each of them finishes. It describes this all this in one place, in the one function. If you didn't use Promises, we would have to create numerous signals and slots and spread the implementation throughout the application.

 

 

3. Promise chaining

 

 

Promise chaining is a coding pattern where you want to run your asynchronous tasks sequentially. You may need to do this if you wish to use the output of one task as an input to the next.

 

 

When the Button is clicked, we want to start the download of 3 web pages, one after the after. If downloads are successful, you will see the web page's title. If any task fails, we do not continue downloading. (N.B. here, the download function is real. The download function returns the web page's title).

 

    Button {
      text: qsTr( "Test Promise chaining" )
      onClicked: {
        download( "GET", "https://community.esri.com/groups/appstudio" )
        .then( (data) => {
          console.log( data.title )
          return download( "GET", "https://appstudio.arcgis.com" )
        } )
        .then( (data) => {
          console.log( data.title )
          return download( "GET", "https://community.esri.com/groups/survey123" )
        } )
        .then( (data) => {
          console.log( data.title )
        } )
        .catch( (error) => { console.log( error ) } )
      }
    }

View the full PromiseChaining.qml on GitHub Gist.

 

However, due to the https://bugreports.qt.io/browse/QTBUG-71329, Promise chaining doesn't work in AppStudio 3.3, Qt 5.12.1. Please vote to have it fixed! Because of the bug, the app does not run correctly:

 

 

 

4. Promise nesting (alternative to Promise chaining)

 

 

Since Promise chaining doesn't work in AppStudio 3.3, Qt 5.12.1 let's explore some alternatives. This one demonstrates Promises nesting where each subsequent task is nested in the success of the previous task. (N.B. here the download function returns an object containing the status, responseText, and title).

 

    Button {
      text: qsTr( "Test Promise nesting" )
      onClicked: {
        download( "GET", "https://community.esri.com/groups/appstudio" )
        .then( (data) => {
          console.log( data.title )
          download( "GET", "https://appstudio.arcgis.com" )
          .then( (data) => {
            console.log( data.title )
            download( "GET", "https://community.esri.com/groups/survey123" )
            .then( (data) => {
              console.log( data.title )
            } )
            .catch( (error) => { console.log( error ) } )
          } )
          .catch( (error) => { console.log( error ) } )
        } )
        .catch( (error) => { console.log( error) } ) 
      }
    }

View the full PromiseNesting.qml on GitHub Gist.

 

This implementation works, but it is extremely ugly. It is infamously known as callbackhell. You see each subsequent task incurs another level of indentation and another copy of the error handler.

 

 

5. Promise async/await (alternative to Promise chaining)

 

 

async/await is another alternative to Promise chaining. The main characteristic is the use of the new async and await keywords and that the main body reads sequentially and elegantly.

 

    Button {
      text: qsTr( "Test Promise async/await" )
      onClicked: {
        (async () => {
          try {
            console.log( ( await download( "GET", "https://community.esri.com/groups/appstudio") ).title)
            console.log( ( await download( "GET", "https://appstudio.arcgis.com") ).title)
            console.log( ( await download( "GET", "https://community.esri.com/groups/survey123" ) ).title)
          } catch ( error ) {
            console.log( error )
          }
        } )()
      }
    }

View the full PromiseAsyncAwait.qml on GitHub Gist.

 

Unfortunately, this feature didn't make it to AppStudio 3.3, Qt 5.12.1. Help get this into a future release of AppStudio by voting for it at https://bugreports.qt.io/browse/QTBUG-58620.

 

 

6. Promise async/await Babel (alternative to Promise chaining)

 

 

Generator functions made it into AppStudio 3.3, Qt 5.12.1. We can use https://babeljs.io/ to convert the async/await into Generator functions. This version works in AppStudio 3.3, Qt 5.12.1. Here's the converted output:

 

    Button {
      text: qsTr( "Test Promise async/await (Babel)" )
      onClicked: {
        _asyncToGenerator( function*() {
          try {
            console.log( ( yield download( "GET", "https://appstudio.arcgis.com" ) ).title )
            console.log( ( yield download( "GET", "https://community.esri.com/groups/appstudio" ) ).title )
            console.log( ( yield download( "GET", "https://community.esri.com/groups/survey123" ) ).title )
          } catch ( error ) {
            console.log( error )
          }
        } )()
      }
    }

View the full PromiseBabel.qml on GitHub Gist.

 

While waiting for the async/await feature to be implemented, I think the above syntax is compelling.

It is extremely close to async/await syntax and, I think, is significantly better than Promise chaining.

 

To make it work, _asyncToGenerator() and asyncGeneratorStep() functions are required.

 


7. Promise.all and Promise.race

 

 

Promise.all is a special Promise that succeeds by waiting for every sub Promise to succeeds else it fails to report the error from the first failing sub Promise.

 

 

Promise.race is a special Promise in that we are only interested in the first sub Promise that finishes the race. We aren't interested in the completion of the subsequent Promises. We will be notified of the success message or failure error of that first sub Promise.

 

Surprisingly, no matter how many times you try, you find the AppStudio Home Page always wins the race.

 

 

Why is the second Promise always succeeding in the race? That's because the community GeoNet page takes longer to load!

 

 

8. Closing remarks

 

 

I hope this blog helps gives a good overview ofPromises and why they matter in your AppStudio apps.

 

Promises, while new in AppStudio 3.3, Qt 5.12.1 is a feature that other Javascript developers have already been enjoying for some time now.

 

Promises, I believe, work very well with Qt's signal and slot mechanism taking it to a whole new level.

 

Promise chaining and async/await functions do not work. We need your help to make AppStudio come closer to parity with other Javascript developer environments by voting on getting these two bugs fixed:

 

 

Whilst we wait for async/await functions, I highly recommend you use https://babeljs.io/ to get async/await features today.

 

 

9. References

 

 

 

Send us your feedback to appstudiofeedback@esri.com

 

Become an AppStudio for ArcGIS developer! Watch this video on how to sign up for a free trial.

 

Follow us on Twitter @AppStudioArcGIS to keep up-to-date on the latest information and let us know about your creations built using AppStudio to be featured in the AppStudio Showcase.

 

The AppStudio team periodically hosts workshops and webinars; please click on this link to leave your email if you are interested in information regarding AppStudio events.