【问题标题】:AngularJS Async data not showing with promiseAngularJS 异步数据未按承诺显示
【发布时间】:2017-03-06 05:17:44
【问题描述】:

当我打开应用程序时,我没有从控制器获得任何数据,尽管console.log($http...) 会给我我想要的数据数组。我的控制器中的以下代码似乎是在 $http 调用之前加载的。

ActivityService.getAll().then(function(data){
    this.data = data
})

这是我的文件:

_home.html

<h1>This is the Home page</h1>
<div>{{msg}}</div>
<div>{{data}}</div>

app.js

 (function() {
   function config($stateProvider, $urlRouterProvider) {

     $stateProvider
     .state('home', {
            url: '/home',
            templateUrl: 'main/_home.html',
            controller: 'MainCtrl as main',
            resolve: {
                activitiesPromise: function(ActivityService){
                  return ActivityService.getAll();
                }
            }
        })

     $urlRouterProvider.otherwise('home')
 }

 angular
     .module('ProTrak', ['ui.router', 'templates'])
     .config(config);
 })();

MainCtrl.js

(function() {

function MainCtrl($scope, ActivityService) {
    this.msg = "hello wROLD"
    ActivityService.getAll().then(function(data){
        this.data = data
    })
}

angular
    .module('ProTrak')
    .controller('MainCtrl', ['ActivityService', MainCtrl]);

 })();

ActivityService.js

(function() {

  function ActivityService($http) {

    ActivityService.getAll = function() {
      return $http({
        url: '/activities.json',
        method: 'GET'
      });
    }
    return ActivityService
  }

  angular
    .module('ProTrak')
    .factory('ActivityService', ['$http', ActivityService]);
  }
)();

在后端,我认为它正在工作,因为我可以console.log 数据。访问此 URL http://localhost:3000/activities.json 时,我得到了正确的 json

[{"id":1,"title":"first","description":"hello world","created_at":"2017-03-05T22:43:08.356Z","updated_at":"2017-03-05T22:43:08.356Z","workouts":[]},{"id":2,"title":"first","description":"hello world","created_at":"2017-03-05T22:43:38.313Z","updated_at":"2017-03-05T22:43:38.313Z","workouts":[]}]

宝石文件

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.6'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc

gem 'angular_rails_csrf'
gem 'angular-rails-templates'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem 'responders', '~> 2.0'
# Use Unicorn as the app server
# gem 'unicorn'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :production do
    gem 'pg'
    gem 'rails_12factor'
end


group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'

  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
end

解决方案:

控制器:

(function() {

function MainCtrl($scope, activitiesPromise) {
    $scope.msg = "hello wROLD"
    $scope.data = activitiesPromise.data
}

angular
    .module('ProTrak')
    .controller('MainCtrl', ['$scope', 'activitiesPromise', MainCtrl]);

 })();

app.js

 (function() {
   function config($stateProvider, $urlRouterProvider) {

     $stateProvider
     .state('home', {
            url: '/home',
            templateUrl: 'main/_home.html',
            controller: 'MainCtrl',
            resolve: {
                activitiesPromise: ['ActivityService', function(ActivityService){
                    return ActivityService.getAll();
                }]
            }
        })

     $urlRouterProvider.otherwise('home')
 }

 angular
     .module('ProTrak', ['ui.router', 'templates'])
     .config(config);
 })();

ActivityService.js

(function() {

  function ActivityService($http) {

    ActivityService.getAll = function() {
      return $http({
        url: '/activities.json',
        method: 'GET'
      });
    }
    return ActivityService
  }

  angular
    .module('ProTrak')
    .factory('ActivityService', ['$http', ActivityService]);
  }
)();

【问题讨论】:

  • 'ActivityService.getAll' 不可见
  • 那么问题是通过修复错误的依赖注入来解决的?
  • 是的,$scope 有问题。

标签: javascript ruby-on-rails angularjs json asynchronous


【解决方案1】:

问题是由于您在以下位置进行了错误的依赖注入:

(function() {

function MainCtrl($scope, ActivityService) {  // <-- First param is $scope
    this.msg = "hello wROLD"
    ActivityService.getAll().then(function(data){
        this.data = data
    })
}

angular
    .module('ProTrak')
    .controller('MainCtrl', ['ActivityService', MainCtrl]); // <-- First dependency injecttion is ActivityService

 })();

要么从MainCtrl 中删除$scope,要么添加$scope 作为第一个依赖注入。

可能的解决方案:

1:

(function() {

function MainCtrl(ActivityService) {  // <-- Removed $scope
    this.msg = "hello wROLD"
    ActivityService.getAll().then(function(data){
        this.data = data
    })
}

angular
    .module('ProTrak')
    .controller('MainCtrl', ['ActivityService', MainCtrl]);

 })();

2:

(function() {

function MainCtrl($scope, ActivityService) {  // <-- First param is $scope
    this.msg = "hello wROLD"
    ActivityService.getAll().then(function(data){
        this.data = data
    })
}

angular
    .module('ProTrak')
    .controller('MainCtrl', ['$scope', 'ActivityService', MainCtrl]); // <-- Added $scope as the first dependency injecttion.

 })();

现在关于数据部分,由于您已经使用$stateProvider 解决了promise,您应该将MainCtrl 函数更改为类似(假设您使用样式#1):

(function() {

    function MainCtrl(activitiesPromise) {  // <-- Added activitiesPromise resolved data
        this.msg = "hello wROLD";
        this.data = activitiesPromise.data;
    }

    angular
        .module('ProTrak')
        .controller('MainCtrl', ['activitiesPromise', MainCtrl]);

 })();

【讨论】:

  • 谢谢,这解决了部分问题。我期待在我的home.html 文件中从{{main.data}} 回来。目前,我没有得到任何东西。我尝试console.log($http({ url: '/activities.json', method: 'GET' });),我确实得到了它的响应,其中包括一个带有我想要的对象的数组。s
  • 我看到您正在使用$stateProvider 来解析ActivityService.getAll() 数据。那么你为什么要在你的MainCtrl 中注入ActivityService 工厂?
  • 我已经更新了我的答案,其中提到了您应该如何更改 MainCtrl 控制器功能。
  • 这很有趣,因为当我有.controller('MainCtrl', ['ActivityService', MainCtrl]); 时它不起作用,但它适用于.controller('MainCtrl', ['activitiesPromise', MainCtrl]);。
  • @Leogoesger 那是因为你在 resolve 中的东西可以直接注入控制器。另外,我的回答是您解决的问题之一:)
【解决方案2】:

我认为您在app.js 中的解析存在注入问题。尝试像这样解决..

activitiesPromise: ['ActivityService', function(ActivityService){
    return ActivityService.getAll();
}]

【讨论】:

    【解决方案3】:
    angular.module('ProTrak')
      .service('ActivityService', function ($http, ENV) {
    
        this.getAll = function ($username) {    
           return $http({
            url: '/activities.json',
            method: 'GET'
          });
        };
    
    }
    

    使用这种模式会更好地解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 1970-01-01
      • 2018-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多