2016-01-17 36 views
3

到目前爲止,學習現有的stackoverflow答案總是幫助我,我總能找到答案,但現在我真的被卡住了。如何確保工廠承諾在指令執行前解決

我正在構建一個應用程序,它使用指令來創建日曆月類型框。

<app2directive class="column_50" jahr="2016" mon="November"></app2directive> 

因此該指令代碼隔離範圍和利用templateUrl文件提請日曆月

App.directive('app2directive',function(YEARS, MONTHS, DAYS){ 

return { 
    restrict:"ACE", 
    scope:{}, 
    replace:true, 
    templateUrl:"templates/cal_directive3.html", 
    controller: function ($scope, $attrs, $injector, $log, YEARS, MONTHS, DAYS) {   var factoryName = "datumFactory" ; 
     var factoryTonnen = "jsonsrc" ; 
     var factoryInstance = $injector.get(factoryName) ; 
     var tonnenInstance = $injector.get(factoryTonnen) ; 

     var wtf = $scope.jsondata.get().then(function(promise){ 
      console.log("jsondata", promise) ; 
      //$scope.tonnen = promise ; 
     }, function(error){ 
      console.log("error", error) ; 
     }) ; 


}); 

在我使用$注射器注入工廠運行在$ http請求的那一刻閱讀帶有數據的json文件,例如假期或特定於所選年份和月份的其他靜態信息。

App.factory('jsonsrc', function($http, $q){ 
return { 
    get: function(){ 
     var deferred = $q.defer() ; 
     $http.get('termine_2016.json') 
      .success(function(data, status, headers, config) { 
       deferred.resolve(data) ; 
      }).error(function(data, status, headers, config) { 
       console.log("[jsonsrc] request didnot work!"); 
       deferred.reject(data) ; 
      }) ; 
     return deferred.promise ; 
    } 
} 

});

它的效果是,對$ http的同一調用運行12次全年頁面加載。

我的問題是重構文件,以便我可以優先將json數據加載到主控制器中,並且指令作用域可以從父作用域繼承。

就其性質而言,該呼叫返回承諾。該指令需要等待這個承諾才能解決的方法,但現在我被困在如何去解決這個問題上。提前感謝任何指針!

回答

1

首先$ HTTP已經返回一個承諾,你可以這樣做:

return $http.get(...) 

PS:你可以鏈的承諾,所以如果你有一些預處理做你能做的

return $http.get(..).then(function(response){ 
    var data = response.data; 
    [..process..] 
    **return data;** 
}, function(rejection){ 
    // do some stuff 
}); 

二:一般你將數據綁定到你的指令(例如ng-model),然後調用控制器中的服務(我的意思是視圖控制器)。爲了處理數據的異步加載,請使用範圍:$ watch或attrs。$觀察模型,以便使用加載的數據刷新指令。

無論您如何加載數據或在應用程序中更改數據,這都會強制不會將指令與數據加載的方式綁定,從而使數據可重用。

請注意我以粗體顯示的內容,您無法忘記該內容,否則下次撥打電話時將無法處理您的數據。

最後:通常是由指令API提供的鏈接功能,你可以有:

link : function(scope, element, attrs){ 
    attrs.$observe('myVariable', function(){ 
     // refresh your internal state of the directive here 
    }); 
} 

「MYVARIABLE」在你的指令調用meanning你有一個ATTR我的變量:

和「myData的」裝在視圖controllerlike這樣的:

jsonrc.get().then(function(response){ 
    $scope.myData = response.data; 
}); 

如果你想走得更遠,我建議你建立一個服務您的

App.service('MyService',['$http', function($http){ 
    var promise = $http.get([URL]); 
    return function(){ // this is your service 
     var me = this; 
     promise.then(function(response){ 
      this.data = response.data; 
     }); 
    } 
}]); 

所以現在你可以在你的主控制器使用:節假日服務,所以你只能在你的應用程序啓動時加載的數據scope.data = MyService.data;或者甚至在你的指令中使用它,或者如果你想使用一些吸氣劑,這通常更好,但並不總是相關的。

如果我忘記了任何告訴我。

0

我認爲這可能有幫助。

  • 首先添加異步調用到父控制器(指令的母公司 控制器)。
  • 然後隔離你的指令的範圍。併爲其添加模型。

scope: { 
 
    data: '=', 
 
}

  • 在你的控制器中添加像變量:$scope.directiveData = {}
  • 與異步調用的結果分配一個變量的值。與data<mydirective data="directiveData"></mydirective>
  • 使用此變量在你的模板,或者scope.data上鍊接:
  • 顯然它傳遞給你的指令。

也許你將需要directiveData嘲笑數據,或只加一個NG,如果以防止崩潰(試圖顯示其數據的第一時間,和directiveData是空的對象)。

0

讓您的工廠保存httpPromise並僅創建一次。

App.factory('jsonsrc', function($http){ 
    var httpPromise; 
    function load() { 
     httpPromise = $http.get('termine_2016.json') 
      .then(function onFullfilled(response) { 
        //return data for chaining 
        return response.data; 
      }).catch(function onRejected(response) { 
        console.log("[jsonsrc] request didnot work!"); 
        //throw to reject promise 
        throw response.status; 
      }); 
      return httpPromise; 
     }; 
     function get() { 
      if (httpPromise) return httpPromise; 
      //Otherwise 
      return load(); 
     }; 
     return { load: load, 
       get: get 
      }; 
}); 

注意,我除去$q.defer和代替.then.catch方法。 .success.error方法已被棄用;請參閱AngularJS $http Service API Reference -- deprecation notice

然後,您可以簡化您的指令:

App.directive('app2directive',function(){ 
    return { 
     restrict:"ACE", 
     scope:{}, 
     replace:true, 
     templateUrl:"templates/cal_directive3.html", 
     controller: function ($scope, $attrs, jsonsrc, $log, YEARS, MONTHS, DAYS) { 
      jsonsrc.get().then (function (data) { 
       $scope.tonnen = data ; 
      }).catch (function(error){ 
       console.log("error", error) ; 
      }); 
     }) 
    } 
}); 

這種方式來實現,該jsonsrc工廠執行XHR得到的只有一次,但app2directive的每個實例可以爲自己的分離範圍檢索數據。