How to remove undefined error in angular js?

2019-08-31 11:23发布

问题:

How to remove undefined error in angular js ?Actually i am trying to load data in using resolve and use that data in controller but on controller i am getting undefined why ?

resolve: {
    message: function (testservice) {
        return testservice.getdata();
    },
    message2: function (testservice) {
        return testservice.getTodo();
    },
    message3: function (testservice) {
        return testservice.getGithub();
    }
}

use the controller

.controller('b', function($scope, $stateParams, $state, $ionicHistory,message) {
    console.log("controller is loaded"+message)
})

// undefined in this console

console.log("controller is loaded"+message)

plinker http://plnkr.co/edit/siqCUS3jUKVQz6pxmC50?p=preview

回答1:

I would say, that you are almost there.

Just the service/factory must return something. I mean here:

...
message: function(testservice) {
      return testservice.getdata();
}

we expect something... and there was nothing

I added one line return data; and there is that updated plunker

.factory('testservice', ['$http',
  function testservice($http) {
    // interface

    // implementation
    function getData() {

      return $http.get("http://jsonplaceholder.typicode.com/photos")
        .then(function(data) {
          console.log(data)

          // HERE - this line was missing
          // return something here
          return data;

        }, function(error) {
          console.log(error)
        })

EXTEND: How to show some view ...loading... before resolve is done?

Based on some comments I extended the example here. It is now showing this view:

loadingB.html

<div >
  <div ui-view="">
    <h2>...loading...</h2>
  </div>
</div>

which is a view of a brand new parent state 'loadingB':

.state('loadingB', {
  redirectTo: "b",
  templateUrl : "loadingB.html",
})

It injects the above view loadingB.html in position of original state 'b'. And it has one property redirectTo: "b", which is managed by this small piece of code:

.run(['$rootScope', '$state', function($rootScope, $state) {
    $rootScope.$on('$stateChangeSuccess', function(evt, to, params) {
      if (to.redirectTo) {
        evt.preventDefault();
        $state.go(to.redirectTo, params)
      }
    });
}])

And our service now uses $timeout to get some delay:

.factory('testservice', ['$http', '$timeout',
  function testservice($http, $timeout) { 
    // interface

    // implementation
    function getData() { 

      return $http.get("http://jsonplaceholder.typicode.com/photos")
        .then(function(data) {
          console.log("resolved http")
          return $timeout(function(){
            console.log("after two seconds delay")
            return data;
          }, 2500)
        ...

And finally, we have to redirect to loadingB here

$scope.moveto = function() {
    $state.go('loadingB'); 
}

And also make the 'b' child of 'laodingB'

.state("b", {
  parent: "loadingB", 
  templateUrl: "b.html",
  url: "/b",
  controller: 'b', 
  resolve: { 
    message: function(testservice) {
      return testservice.getdata();
    },

Check it all here



回答2:

Radim Koehler has the correct answer, or even easier, just return the promise from the getData function in the service:

function getData() { 
      return $http.get("http://jsonplaceholder.typicode.com/photos");
}


回答3:

If you want to resolve state before going into view, then you need to do few things. resolve you state like this

.state('app.b', {
  url: "/b",
  views: {
    'menuContent': {
      templateUrl: "b.html",
      controller: 'b',
      resolve: {
        apiData: "testservice",
        itemDetailsData: function($q, apiData) {
          var item = apiData.getdata();
          if (item) {
            return $q.when(item);
          } else {
            return $q.reject();
          }
        }
      }
    }
  }
})

in you services you can have factory method like :

.factory('albumService', ['$http', '$q', '$ionicLoading', '$timeout', albumFn])
function albumFn($http, $q, $ionicLoading, $timeout) {
return {
getAlbums: function() {
  $ionicLoading.show({
    content: '<i class="icon ion-loading-d"></i>',
    animation: 'fade-in',
    showBackdrop: true,
    maxWidth: 200,
    showDelay: 5
  });

  var def = $q.defer();
  $http.get("data.json")
    .success(function(data) {
     $ionicLoading.hide();
      def.resolve(data);
    })
    .error(function() {
     $ionicLoading.hide();
      def.reject("Failed to get albums");
    });

  return def.promise;

    }
  }
 }

I have created similar plunker demo here