Cryptic failure of custom AngularJS service

1

I am trying to follow along with the mostly good but dated book Getting MEAN with MongoDB, Express, AngularJS and Node and am in a section where hardwired data in a controller is being replaced with a call to a custom API that I already built and is certainly working, as determined by tests with curl. Before I implemented this change, the page looked like this:

functional

Now it looks like this:

non-functional

Here is the source in question:

var _isNumeric = function (n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
};

var formatDistance = function () {
  return function (distance) {
    var roundedDistance, unit;

    if (distance && _isNumeric(distance)) {
      if (distance > 1) {
        roundedDistance = parseFloat(distance).toFixed(1);
        unit = 'km';
      } else {
        roundedDistance = parseInt(distance * 1000, 10);
        unit = 'm';
      }

      return roundedDistance + ' ' + unit;
    } else {
      return '?';
    }
  };
};

var ratingStars = function () {
  return {
    scope: {
      thisRating: '=rating'
    },
    templateUrl: '/angularjs/rating-stars.html'
  };
};

var loc8rData = function ($http) {
  return $http.get('/api/locations?lng=-0.79&lat=51.3&maxDistance=25');
};

var locationListCtrl = function ($scope, loc8rData) {
  $scope.message = 'Searching for nearby places...';

  loc8rData.success(function (data) {
    $scope.message = data.length > 0 ? '' : 'No locations found';
    $scope.data = { locations: data };
  }).error(function (err) {
    $scope.message = 'Sorry, something\'s gone wrong.';
    console.log(err);
  });
};

angular
  .module('loc8r', [])
  .controller('locationListCtrl', locationListCtrl)
  .filter('formatDistance', formatDistance)
  .directive('ratingStars', ratingStars)
  .service('loc8rData', loc8rData);

The following not very informative warnings and errors were found in the console:

[Exception... "Component returned failure code: 0xc1f30001 (NS_ERROR_NOT_INITIALIZED) [nsIMessageSender.sendAsyncMessage]"  nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)"  location: "JS frame :: resource://gre/modules/ExtensionUtils.jsm :: sendAsyncMessage :: line 505"  data: no]  (unknown)
[Exception... "Component returned failure code: 0xc1f30001 (NS_ERROR_NOT_INITIALIZED) [nsIMessageSender.sendAsyncMessage]"  nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)"  location: "JS frame :: resource://gre/modules/ExtensionUtils.jsm :: sendAsyncMessage :: line 505"  data: no]  (unknown)
Invalid chrome URI: /
Cannot send function call result: other side closed connection (call data: ({path:"tabs.remove", args:[23]}))
[Exception... "Component returned failure code: 0xc1f30001 (NS_ERROR_NOT_INITIALIZED) [nsIMessageSender.sendAsyncMessage]"  nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)"  location: "JS frame :: resource://gre/modules/ExtensionUtils.jsm :: sendAsyncMessage :: line 505"  data: no]  (unknown)
Loading failed for the <script> with source “https://js-sec.indexww.com/ht/p/185901-159836282584097.js”.  ask:171
Attempt to set a forbidden header was denied: Connection  805599773-lcs_client_bin.js:99:385
This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features!  ask
Error: Could not establish connection. Receiving end does not exist.  undefined
Attempt to set a forbidden header was denied: Connection  805599773-lcs_client_bin.js:99:385
Content Security Policy: Ignoring ‘x-frame-options’ because of ‘frame-ancestors’ directive.  (unknown)
[Exception... "Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]"  nsresult: "0x80004002 (NS_NOINTERFACE)"  location: "JS frame :: chrome://browser/content/browser.js :: onStateChange :: line 5174"  data: no]  (unknown)
NS_NOINTERFACE: Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]  WebNavigationContent.js:220
[Exception... "Component returned failure code: 0xc1f30001 (NS_ERROR_NOT_INITIALIZED) [nsIMessageSender.sendAsyncMessage]"  nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)"  location: "JS frame :: resource://gre/modules/ExtensionUtils.jsm :: sendAsyncMessage :: line 505"  data: no]  (unknown)
[Exception... "Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]"  nsresult: "0x80004002 (NS_NOINTERFACE)"  location: "JS frame :: chrome://browser/content/browser.js :: onStateChange :: line 5174"  data: no]  (unknown)
NS_NOINTERFACE: Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]  WebNavigationContent.js:220
Loading failed for the <script> with source “blob:https://github.com/b435c6f8-48e4-4b26-a514-f8afc76aad14”.  loc8r:1
Content Security Policy: The page’s settings blocked the loading of a resource at self (“script-src https://assets-cdn.github.com”). Source: ;!function(){var t=0,e=function(t,e){ret....  loc8r:1
Content Security Policy: The page’s settings blocked the loading of a resource at blob:https://github.com/b435c6f8-48e4-4b26-a514-f8afc76aad14 (“script-src https://assets-cdn.github.com”).  (unknown)
[Exception... "Component returned failure code: 0xc1f30001 (NS_ERROR_NOT_INITIALIZED) [nsIMessageSender.sendAsyncMessage]"  nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)"  location: "JS frame :: resource://gre/modules/ExtensionUtils.jsm :: sendAsyncMessage :: line 505"  data: no]  (unknown)
TypeError: this.transport is null[Learn More]  main.js:1514:5
[Exception... "Component returned failure code: 0xc1f30001 (NS_ERROR_NOT_INITIALIZED) [nsIMessageSender.sendAsyncMessage]"  nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)"  location: "JS frame :: resource://gre/modules/ExtensionUtils.jsm :: sendAsyncMessage :: line 505"  data: no]  (unknown)

What may be substantially more helpful is the diff between the hardwired version and the new, failed revision:

diff --git a/public/angularjs/loc8r.js b/public/angularjs/loc8r.js
index 467f5c7..b5f800e 100644
--- a/public/angularjs/loc8r.js
+++ b/public/angularjs/loc8r.js
@@ -31,35 +31,25 @@ var ratingStars = function () {
   };
 };

-var locationListCtrl = function ($scope) {
-  $scope.data = {
-    locations: [{
-       'name': 'Starcups',
-       'address': '125 High Street, Reading, RG6 1PS',
-       'rating': 3,
-      'facilities': ['Hot Drinks', 'Food', 'Premium Wi-Fi'],
-      'distance': 14.6,
-      '_id': '5a27ab691c5e0a989c0634da'
-    }, {
-       'name': 'Café Hero',
-       'address': '125 High Street, Reading, RG6 1PS',
-       'rating': 4,
-      'facilities': ['Hot Drinks', 'Food', 'Premium Wi-Fi'],
-      'distance': 14.6,
-      '_id': '5a2cdcc9877c0bf8cdf47355'
-    }, {
-       'name': 'Burger Queen',
-       'address': '125 High Street, Reading, RG6 1PS',
-       'rating': 2,
-      'facilities': ['Food', 'Premium Wi-Fi'],
-      'distance': 14.6,
-      '_id': '5a2ce5ae877c0bf8cdf47358'
-    }]
-  };
+var loc8rData = function ($http) {
+  return $http.get('/api/locations?lng=-0.79&lat=51.3&maxDistance=25');
+};
+
+var locationListCtrl = function ($scope, loc8rData) {
+  $scope.message = 'Searching for nearby places...';
+
+  loc8rData.success(function (data) {
+    $scope.message = data.length > 0 ? '' : 'No locations found';
+    $scope.data = { locations: data };
+  }).error(function (err) {
+    $scope.message = 'Sorry, something\'s gone wrong.';
+    console.log(err);
+  });
 };

 angular
   .module('loc8r', [])
   .controller('locationListCtrl', locationListCtrl)
   .filter('formatDistance', formatDistance)
-  .directive('ratingStars', ratingStars);
+  .directive('ratingStars', ratingStars)
+  .service('loc8rData', loc8rData);

It seems obvious that I did something wrong when I created this service but looking through newer AngularJS tutorial material doesn't appear to be helping me at all.

If you're curious, the whole shebang can be found here (note that running it requires a database to be restored from a dump):

https://github.com/readyready15728/loc8r

EDIT: I've figured out what went wrong. The Firefox browser console now has the great, ingenious default setting of requiring me to show console.log() output explicitly. Once I did this I could start debugging more effectively. This is what solved the problem:

var locationListCtrl = function ($scope, loc8rData) {
  $scope.message = 'Searching for nearby places...';

  loc8rData.then(function (response) {
    $scope.message = response.data.length > 0 ? '' : 'No locations found';
    $scope.data = { locations: response.data };
  }, function (err) {
    $scope.message = 'Sorry, something\'s gone wrong.';
    console.log(err);
  });
};

Briefly, I used .then() rather than .success() and .error() and realized that the object returned by $http.get() is not the data, but has the data as a member.

javascript
angularjs
mean-stack
angularjs-service
asked on Stack Overflow Dec 26, 2017 by readyready15728 • edited Dec 26, 2017 by readyready15728

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0