6

Tôi đã chọn một dự án và tôi đang cố trả lại một số dữ liệu từ dịch vụ cho bộ điều khiển của mình. Tôi đã ở đây khoảng 12 giờ và đã thử các phương pháp khác nhau. Tất cả chúng thường dẫn đến cùng loại 'dữ liệu bị thiếu' này.AngularJS: phạm vi điều khiển sẽ không đồng bộ với lời hứa

Tôi đã thử

  • sử dụng $ tài nguyên thay vì $ http
  • đặt $http.get ngay bên trong bộ điều khiển mà không sử dụng lời hứa
  • dịch vụ như một dịch vụ thực tế (thay vì một nhà máy) mà không a return
  • xây dựng nhà máy theo nhiều cách khác nhau để trả lại dữ liệu ở nhiều định dạng khác nhau
  • sử dụng setTimeout và $ apply

tôi cảm thấy những gì tôi có bây giờ là một đơn giản như tôi có thể nhận được nó, và tất cả mọi thứ tôi đã đọc nói rằng điều này sẽ làm việc

angularjs-load-data-from-service

angular-controller-cant-get-data-from-service

angularjs-promises-not-firing-when-returned-from-a-service

angularjs-promise-not-resolving-properly

angularjs-promise

Các liên kết này chỉ từ hôm nay.

tôi nghĩ có thể có một phạm vi vấn đề $, như trong quá khứ tôi đã nhìn thấy $ phạm vi không nhận được dữ liệu khi nhiều bộ điều khiển làm quen, tuy nhiên các trang web chỉ đơn giản tuyên bố một bộ điều khiển trong index.html như <body ng-app="myApp" ng-controller="BodyCtrl"> thiết lập. Các chính app.js sử dụng trạng thái (từ ui-router Tôi tin) như vậy ...

.state('app.view', { 
    url: '/view', 
    templateUrl: 'views/view.tpl.html', 
    controller: 'MyCtrl' 
    }) 

để gắn bộ điều khiển đến các trang khác nhau. Ngoài ra, trang web có một vài bộ điều khiển khác nhận dữ liệu từ các dịch vụ mà tôi đã xem qua đầu tiên dưới dạng mẫu, tuy nhiên, dữ liệu và trả về phức tạp hơn nhiều so với những gì tôi đang cố gắng truy cập. Tóm lại, các bộ điều khiển đang truy cập dữ liệu được cung cấp từ các dịch vụ. Tất cả chúng đều sử dụng tài nguyên $, đó là cách tôi bắt đầu với vấn đề này. Tôi đã bị mắc kẹt với $ http vì nó nên hoạt động và tôi muốn làm việc này trước khi tôi chuyển sang thứ gì đó 'cấp cao hơn'. Ngoài ra, tôi chỉ cần GET từ các thiết bị đầu cuối, vì vậy cảm thấy $ tài nguyên là quá mức cần thiết.

dịch vụ

.factory('MyService', ['$http', '$q', '$rootScope', function ($http, $q, $rootScope) { 
    var defer = $q.defer(); 
    var factory = {}; 
    factory.all = function() { 
     $http({method: 'GET', url: 'http://URLtoJSONEndpoint'}). 
      success(function (data, status, headers, config) { 
       console.log('data success', data); 
       defer.resolve(data); 
      }). 
      error(function (data, status, headers, config) { 
       console.log('data error'); 
       defer.reject(data); 
      }); 

     return defer.promise; 
    }; 
    return factory; 
}]); 

khiển

.controller('MyCtrl', ['$scope', '$state', '$stateParams', '$rootScope', 'MyService', '$q', function ($scope, $state, $stateParams, $rootScope, MyService, $q) { 
... 
... 
$scope.data = null; 
$scope.object = MyService; 
$scope.promise = MyService.all(); 

MyService.all().then(function (data) { 
    $scope.data = data; 
    console.log("data in promise", $scope.data); 
}) 
console.log("data", $scope.data); 
console.log("object", $scope.object); 
console.log("promise", $scope.promise); 

$http({method: 'GET', url: 'http://URL'}). 
     success(function (data, status, headers, config) { 
      $scope.data = data; 
      console.log('data success in ctrl', data); 
     }). 
     error(function (data, status, headers, config) { 
      console.log('data error'); 
     }); 

    console.log("data after ctrl", $scope.data); 


    angular.forEach($scope.data, function (item) { 
     // stuff that I need $scope.data for 
    } 

console log

Vì vậy, đây là giao diện điều khiển đăng nhập của tôi, và tôi có thể nhận được tại nên muc h, không phải dữ liệu thực tế!Đó là những gì tôi cần. Tôi thậm chí còn phát điên và mở rộng .then(function (data) { để chụp tất cả các chức năng trong bộ điều khiển cần $scope.data. Đó là một con tàu đắm.

***data null*** 
object Object {all: function} 
promise Object {then: function, catch: function, finally: function} 
***data success after ctrl null*** 
data success in ctrl Array[143] 
data success Array[143] 
data in promise Array[143] 
data success Array[143] 

Theo như tôi có thể nói, đây nên làm việc, nhưng tôi không chắc chắn nơi nào khác vấn đề có thể! Có lẽ tôi không hiểu lời hứa làm việc hay giải quyết như thế nào. Tôi đã sử dụng Angular trước với một dự án khác, nhưng tôi đã ở đó lúc bắt đầu và hiểu cách nó được đặt lại với nhau. Dự án này được cấu trúc khác nhau và cảm thấy hỗn loạn hơn nhiều. Tôi muốn đơn giản hóa nó, nhưng tôi thậm chí không thể có được một số dữ liệu đơn giản để trở lại!

Tôi đánh giá cao bất kỳ trợ giúp/phản hồi nào bạn có thể cung cấp trong việc xác định lý do tại sao điều này không hiệu quả, cảm ơn bạn!

EDIT: Vì vậy, câu hỏi đặt ra là tại sao console.log("data", $scope.data) quay lại null/trước lời hứa?

một chút nữa xuống trong bộ điều khiển tôi có điều này

angular.forEach($scope.data, function (item) { 
// stuff 
} 

và nó dường như không có quyền truy cập vào dữ liệu.

EDIT2: Tôi đã thêm $http.get Tôi đã sử dụng bên trong bộ điều khiển, cùng với giao diện điều khiển các bản ghi cho nó và thực sự foreach Tôi cần $scope.data cho

EDIT3:

cập nhật dịch vụ

.service('MyService', ['$http', function ($http) { 
    function all() { 
     return $http({ 
      url: 'http://URL', 
      method: 'GET' 
     }); 
    } 

    return { 
     all: all 
    } 
}]); 

bộ điều khiển cập nhật

MyService.all().success(function (data) { 
     $scope.data = data; 

     angular.forEach($scope.data, function (item) { 

      // Turn date value into timestamp, which is needed by NVD3 for mapping dates 
      var visitDate = new Date(item.testDate).getTime(); 

      switch (item.Class) { 
       case "TEST": 
        testData.push(
         [ 
          visitDate, 
          item.Total 
         ] 
        ); 

      } 

     }); 

     console.log("test Data in success", testData); 
    }); 


$scope.testData = [ 
     { 
      "key": "Test", 
      "values": testData 
     } 
    ]; 

Vì vậy, $scope.testData cần được sử dụng trong chế độ xem (biểu đồ nvd3) và không nhận được dữ liệu.

SOLUTION

MyService.all().success(function (data) { 
     $scope.data = data; 

     angular.forEach($scope.data, function (item) { 

      // Turn date value into timestamp, which is needed by NVD3 for mapping dates 
      var visitDate = new Date(item.testDate).getTime(); 

      switch (item.Class) { 
       case "TEST": 
        testData.push(
         [ 
          visitDate, 
          item.Total 
         ] 
        ); 
      } 

     }); 

     console.log("test Data in success", testData); 

     $scope.testData = [ 
     { 
      "key": "Test", 
      "values": testData 
     } 
    ]; 
    }); 
+2

Vì vậy, câu hỏi của bạn là tại sao 'console.log (" data ", $ scope.data); // => dữ liệu null'? Nếu có, thì có thể vì nhật ký thực hiện trước khi cuộc gọi async kết thúc.Sidenote hai cuộc gọi đến 'MyService.all();' sẽ thực sự kích hoạt hai yêu cầu. Tôi nghĩ điều đầu tiên là không cần thiết. – Yoshi

+1

Vâng, chính xác! Cảm ơn bạn đã chỉ ra điều này, không phải là rất rõ ràng – mykepwnage

+1

Tôi muốn bắt đầu bằng cách làm cho nó hoạt động bên trong bộ điều khiển của bạn, vì vậy thành công làm $ scope.data = data; Khi bạn có thể thấy cuộc gọi làm việc thành công thì bắt đầu refatoring với các dịch vụ, nghĩ rằng bạn đang thêm phức tạp. $ http đã trả về một lời hứa, vì vậy bạn không cần phải sử dụng một lời hứa khác. https://docs.angularjs.org/api/ng/service/$http – LightningShield

Trả lời

5

Đây có thể là một ví dụ rất đơn giản về cách dịch vụ của bạn có thể trông giống như:

app.service('MyService', ['$http', function ($http) { 
    function all() { 
    return $http({ 
     url: 'data.json', 
     method: 'GET' 
    }); 
    } 

    return { 
    all: all 
    } 
}]); 

Trong bộ điều khiển bạn sử dụng nó như vậy:

app.controller('AppCtrl', ['$scope', 'MyService', function ($scope, MyService) { 
    $scope.data = null; 

    MyService.all().success(function (data) { 
    $scope.data = data; 

    // init further handling of `.data` here. 
    }); 
}]); 

Demo: http://plnkr.co/edit/l8pF8Uaa312A8kPtaCNM?p=preview


Để trả lời câu hỏi tại sao giao diện điều khiển bản ghi data null: Đây chỉ đơn giản là vì các bản ghi sẽ xảy ra trước khi kết thúc cuộc gọi async.

0

Tôi đang gặp phải vấn đề tương tự. Tôi giải quyết vấn đề đó bằng cách sử dụng $rootScope bên trong lời hứa thay vì $scope.So$rootScope.data sẽ có sẵn trong console.log

Các vấn đề liên quan