簡體   English   中英

如何確保工廠承諾在指令執行之前解析

[英]How to ensure factory promise resolves before directive executes

到目前為止,研究現有的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 ) ;
        }) ;


});

目前,我使用$ injector注入一個工廠,該工廠運行$ http-request來讀取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數據加載到主控制器中,並且指令范圍可以從父作用域繼承。

從本質上講,呼叫會返回一個承諾。 該指令需要等待該承諾在其繼續進行之前解決的手段,但現在我仍然堅持如何去做。 提前感謝任何指針!

第一個$ 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'在你的指令調用中意味着你有一個attr my-variable:

並且“myData”在視圖控制器中加載如下:

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; 或者甚至在你的指令中使用它,或者如果你想要使用一些吸氣劑,這通常會更好,但並不總是令人驕傲。

如果我忘了什么告訴我。

我認為這可能會有所幫助。

  • 首先將異步調用添加到父控制器(指令的父控制器)中。
  • 然后隔離指令的范圍。 並為其添加模型。

 scope: { data: '=', } 

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

可能你需要為directiveData模擬數據,或者只是添加一個ng-if來防止崩潰(當第一次嘗試顯示數據時,並且directiveData是空對象)。

讓您的工廠保存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服務API參考 - 棄用通知

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

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 GET,但app2directive每個實例化app2directive可以檢索其自己的隔離范圍的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM