getDataSourceProxies() throws TypeError

2372
6
Jump to solution
11-05-2015 04:36 PM
BenSaunders1
New Contributor III

I'm trying to get at an external data source within the Operations Dashboard with my custom JavaScript widget - this external data source would be one in addition to the data source configured with my widget. So I'm using the getDataSourceProxies() method on the WidgetProxy class. However, it throws the following error:

TypeError
 "TypeError: Cannot call method 'map' of undefined
    at null.<anonymous> (http://js.arcgis.com/3.14/esri/opsdashboard/core/ExtensionBase.js:11:181)
    at http://js.arcgis.com/3.14/init.js:167:296
    at k (http://js.arcgis.com/3.14/init.js:189:431)
    at m (http://js.arcgis.com/3.14/init.js:189:357)
    at resolve (http://js.arcgis.com/3.14/init.js:191:441)
    at a (http://js.arcgis.com/3.14/init.js:190:311)
    at http://js.arcgis.com/3.14/init.js:190:217
    at k (http://js.arcgis.com/3.14/init.js:189:431)
    at m (http://js.arcgis.com/3.14/init.js:189:357)
    at resolve (http://js.arcgis.com/3.14/init.js:191:441)
    ----------------------------------------
    rejected at a (http://js.arcgis.com/3.14/init.js:190:337)
    at k (http://js.arcgis.com/3.14/init.js:190:103)
    at m (http://js.arcgis.com/3.14/init.js:189:357)
    at x.reject (http://js.arcgis.com/3.14/init.js:192:143)
    at a (http://js.arcgis.com/3.14/init.js:190:337)
    at k (http://js.arcgis.com/3.14/init.js:190:89)
    at m (http://js.arcgis.com/3.14/init.js:189:357)
    at resolve (http://js.arcgis.com/3.14/init.js:191:441)
    at a (http://js.arcgis.com/3.14/init.js:190:311)
    at http://js.arcgis.com/3.14/init.js:190:217
    ----------------------------------------
Error
    at then.b.then (http://js.arcgis.com/3.14/init.js:192:253)
    at declare.hostReady (http://localhost:5001/Operations%20Dashboard%20Extensions/MyWidget/MyWidget.js:79:41)
    at l._hostReady (http://js.arcgis.com/3.14/esri/opsdashboard/core/ExtensionBase.js:8:186)
    at http://js.arcgis.com/3.14/init.js:167:296
    at k (http://js.arcgis.com/3.14/init.js:189:431)
    at m (http://js.arcgis.com/3.14/init.js:189:357)
    at resolve (http://js.arcgis.com/3.14/init.js:191:441)
    at a (http://js.arcgis.com/3.14/init.js:190:311)
    at http://js.arcgis.com/3.14/init.js:190:217
    at k (http://js.arcgis.com/3.14/init.js:189:431)" init.js:199

The code in my custom widget is:

define([
    "dojo/_base/declare",
    "esri/opsdashboard/WidgetProxy"
], function(
    declare,
    WidgetProxy
) {
    return declare("MyWidget", [WidgetProxy], {
        /* Override */
        hostReady: function() {
            this.inherited(arguments);

            this.getDataSourceProxies().then(function(aDataSourceProxies) {
                console.log("Data source proxies:", aDataSourceProxies);
            });
        }
    });
});

My manifest file includes "useDataFromView": true. And I indeed have an external data source loaded:

Any thoughts on how to troubleshoot this? Or am I taking the wrong approach at getting at this external data source from my custom widget?

Thanks!

Ben

1 Solution

Accepted Solutions
HoriaTudosie
Occasional Contributor II

Hi Ben,

just replace the original function with this:

define([

  "dojo/_base/declare",

  "dojo/_base/lang",

  "dojo/Deferred",

  "esri/opsdashboard/core/messageHandler",

  "esri/opsdashboard/core/errorMessages",

...

], function (declare, lang, Deferred, messageHandler, ErrorMessages,

...

    return declare("TimeChartWidgetConfig", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin,

      WidgetConfigurationProxy], {

      templateString: templateString,

    hostReady: function(){

      this.getDataSourceProxies().then(

          function(dataSources) { console.log(dataSources); },

          function(err) { console.log('error: '+err); }

      );

...

    },

   getDataSourceProxies: function() {

        return !this._isHostInitialized()

        ? (new Deferred).reject(Error(ErrorMessages.hostNotReady))

        : messageHandler._sendMessageWithReply({functionName: "getDataSources"}).then(lang.hitch(this, function(a) {

            return (new Deferred).resolve(a.dataSources);

        }))

    },

...

View solution in original post

0 Kudos
6 Replies
HoriaTudosie
Occasional Contributor II

hi Ben,

the then() function has three callback arguments, as per

dojo/promise/Promise — The Dojo Toolkit - Reference Guide

so, the code would be:

    hostReady: function(){

        this.getDataSourceProxies().then(

          function(r){ console.log('r'); console.log(r); },

          function(e){ console.log('e'); console.log(e); },

          function(p){ console.log('p'); console.log(p); }

          )

...

still the output is:

e

TypeError {}

and I don't know why.
Did you find any solution yet?

0 Kudos
HoriaTudosie
Occasional Contributor II

Hi Ben,

just replace the original function with this:

define([

  "dojo/_base/declare",

  "dojo/_base/lang",

  "dojo/Deferred",

  "esri/opsdashboard/core/messageHandler",

  "esri/opsdashboard/core/errorMessages",

...

], function (declare, lang, Deferred, messageHandler, ErrorMessages,

...

    return declare("TimeChartWidgetConfig", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin,

      WidgetConfigurationProxy], {

      templateString: templateString,

    hostReady: function(){

      this.getDataSourceProxies().then(

          function(dataSources) { console.log(dataSources); },

          function(err) { console.log('error: '+err); }

      );

...

    },

   getDataSourceProxies: function() {

        return !this._isHostInitialized()

        ? (new Deferred).reject(Error(ErrorMessages.hostNotReady))

        : messageHandler._sendMessageWithReply({functionName: "getDataSources"}).then(lang.hitch(this, function(a) {

            return (new Deferred).resolve(a.dataSources);

        }))

    },

...

0 Kudos
BenSaunders1
New Contributor III

I knew as soon as I would be on leave someone would answer this! Sorry for not responding right away...

The source of the bug seems to be in the ExtensionBase class - inside the ExtensionBase class, it is calling the map method on an object that is presumably and Array. However, it isn't (it is null) because it is looking for a property called "_dataSourceProxies" to run the map method on. What it should be looking for is "dataSources". That's an array. That is also what you've included in your workaround above:

return (new Deferred).resolve(a.dataSources);

So in the meantime I too have taken advantage of the messageHandler._sendMessageWithReply to get at the data sources. I've tried filing a bug report on the support site, but because of my lowly EDN license it won't accept it (not paying for support). So I'm in the process of working through a client.

Thanks very much for your time - I appreciate it!

Ben

HoriaTudosie
Occasional Contributor II

Hi ben,

Did you find any way to subscribe for notifications from the ds we get with this fix?

Normally, the notification from the (single) data source configured in the configuration comes through the method dataSourceExpired (with the parameter dataSource - but this is just the one configured as above...)

I cannot figure out a method to subscribe for notifications from other ds...

0 Kudos
BenSaunders1
New Contributor III

Hey Horia,

No, I haven't looked into that. The addtional datasource I've been working with has been an external one (verses one loaded in a map). And while that datasource is configured to be dynamic and refreshed every 30 seconds, it doesn't refresh itself (monitoring network traffic through Fiddler shows no periodic calls to refresh the data). However, when I query the datasource, it performs a QueryTask and makes the call directly to ArcGIS Server. So in essence I'm getting live data instead of data that is 30 seconds old, which is good. But more appropriate for our discussion here, there's no associated dataSourceExpired event as a result to work with, as there's no active expiration (if that makes any sense at all...). But in our case, we are not dependent on that datasource expiring.

That all being said, there will be a time when we will want/need that! The place I would start looking in is to see if there's anything with the messageHandler class and see if there's somehow a "message" being sent out by the host application of when a datasource expires. It might be worth looking at the dataSourceExpired method to see how it is getting notified as well.

It's too bad that there's nothing associated with the datasource that triggers the event, but instead you have to rely on the dataSourceExpired method, and that's on another class and is passive as you point out - both the datasource and config are more like return variables in this situation rather than arguments!

If you find out more, please follow-up cause it is a mystery to me!

Ben

BenSaunders1
New Contributor III

For those of you keeping score at home, this issue appears to be resolved with the JavaScript API v3.15. Calling getDataSourceProxies() no longer returns an error and instead returns an array of DataSourceProxy objects!