Select to view content in your preferred language

Why is this promise with angular and the esriLoader not returning the query results I expect?

1261
3
03-14-2017 09:25 AM
NicoleSchmidt
Emerging Contributor

I believe I am missing a subtlety in promise chaining when working with the Angularjs esri loader.

Take this example.  It is an angular (1.x) service class.  Note the console.assert on line 17.  I was expecting the GetTestQuery function to return a promise that would resolve to an esri Query object, but this is not what is happening.  Can anyone help me understand what I am missing?

module Demo.Test {
    export class EsriFeatureServiceUtilities {

        static $inject = ['esriLoader'];
        constructor(private esriLoader: any) {
        }


        public RunTestQuery(url: string) {
            var where = "1 = 1";
            return this.QueryTestWithWhere(url, where);
        }

        private QueryTestWithWhere(url: string, where: string) {

            return this.GetTestQuery("1=1").then((query) => {
                console.assert(query.where == "1=1", "Why am I not getting a query object back like I expect?");
                return this.QueryTestLayer(url, query);
            });
        }

        private QueryTestLayer(url: string, query: __esri.Query) {
            return this.esriLoader.require(["esri/tasks/QueryTask"],
                function (QueryTask) {

                    var queryTask = new QueryTask({ url: url });
                    return queryTask.execute(query);

                });
        }

        private GetTestQuery(where: string) {

            return this.esriLoader.require(["esri/tasks/support/Query", "esri/geometry/SpatialReference"],
                function (Query, SpatialReference) {
                    var query: __esri.Query = new Query();
                    query.outFields = ["*"];
                    query.returnGeometry = true;
                    query.where = where;
                    query.outSpatialReference = new SpatialReference(4326);
                    return query;
                });
        }

    }

    angular.module('Demo.Test').service('EsriFeatureServiceUtilities', EsriFeatureServiceUtilities);
}  
Tags (2)
0 Kudos
3 Replies
TomWayson
Esri Contributor

Just to make sure I understand this is TypeScript code using JSAPI 4.x in an Angular 1.x app, right?

I was expecting the GetTestQuery function to return a promise that would resolve to an esri Query object, but this is not what is happening.

What _is_ happening?

Does it get to your `console.assert()`?


Have you tried handling the error side of the promise that's returned (i.e. changing line 19 above to

}, (err) => { console.log(err); });`

0 Kudos
TomWayson
Esri Contributor

Jacob Wasilkowski‌ had an idea on this that gives me an idea. I don't think it's correct to supply _both_ a callback, _and_ use the promise. Maybe something like this:

```

        private GetTestQuery(where: string) {

            return this.esriLoader.require(["esri/tasks/support/Query", "esri/geometry/SpatialReference"]).then(function (Query, SpatialReference) {
                    var query: __esri.Query = new Query();
                    query.outFields = ["*"];
                    query.returnGeometry = true;
                    query.where = where;
                    query.outSpatialReference = new SpatialReference(4326);
                    return query;
                });
        });

```

NicoleSchmidt
Emerging Contributor

Thank you!  That got me to the solution.  The function had to look like this to work:

        private GetTestQuery(where: string) {

            return this.esriLoader.require(["esri/tasks/support/Query", "esri/geometry/SpatialReference"]).then(
                function (results) {
                    var Query = results[0];
                    var SpatialReference = results[1];
                    var query: __esri.Query = new Query();
                    query.outFields = ["*"];
                    query.returnGeometry = true;
                    query.where = where;
                    query.outSpatialReference = new SpatialReference(4326);
                    return query;
                });
        }

Which is a bit awkward, but I understand why it has to be that way.  I would rather load the esri libraries and inject into the service in the service constructor, but I know there are two different loading mechanisms going on here.

It makes me want to consider the exclude and require pattern you have outlined in your blog, although we don't presently use webpack for the rest of the application. 

Thank you very much for taking the time to look at this.