2017-06-21 33 views
1

私は、この問題に関するほとんどの質問は、angular.element($document).readyという角度でのjQuery $(document).ready関数の代替案に関するものですが、テスト可能な/ベストプラクティスの代替これに。angular.element(document)の代わりに.ready

現在、コントローラのコードが実行される前にロードする必要があるBing Mapsを注入しています。作品

angular.element($document).ready(function() { 
    self.map = new Microsoft.Maps.Map(document.getElementById('map'), { 
     credentials: $scope.credentials, 
     enableClickableLogo: false, 
     enableSearchLogo: false, 
     showDashboard: false, 
     disableBirdseye: true, 
     allowInfoboxOverflow: true, 
     liteMode: true, 
     minZoom: 2 
    }); 

    $scope.$watch('zoom', function (zoom) { 
     self.map.setView({animate: true, zoom: zoom}); 
    }); 

    if ($scope.onMapReady) { 
     $scope.onMapReady({ map: self.map }); 
    } 

}); 

を、しかし、私はそれをテストすることができないので、私は、これは間違った用法であると仮定します。

は、現在、私は準備ができて、文書内のコントローラコードをラップします。 ディレクティブに変数を設定しようとしましたが、 $scope.loaded = true;です。ディレクティブリンク関数がヒットした場合は、DOMをロードする必要があります。 「ロードされた」時計は期待通りに動作しますが、マップが設定される前に自然にズームが負荷とのthatsにヒットした

$scope.$watch('loaded', function() { 
    self.map = new Microsoft.Maps.Map(document.getElementById('map'), { 
     credentials: $scope.credentials, 
     enableClickableLogo: false, 
     enableSearchLogo: false, 
     showDashboard: false, 
     disableBirdseye: true, 
     allowInfoboxOverflow: true, 
     liteMode: true, 
     minZoom: 2 
    }); 

    if ($scope.onMapReady) { 
     $scope.onMapReady({ map: self.map }); 
    } 
}); 

$scope.$watch('zoom', function (zoom) { 
    self.map.setView({animate: true, zoom: zoom}); 
}); 

:私はその後で準備ができて文書を交換してみました。私は文書を$timeout機能に変えることができるように感じますが、正しい解決策ではなく回避策であると思われます。angular.element($document).readyの代わりにベストプラクティスの代わりに同じ方法で動作しますが、内容を正しくテストできますか?

+0

このコードのコンテキストは何ですか?通常、角度のあるアプリはドキュメントの準備ができたらブートストラップする必要があるので、このラッパーは少なくともコントローラーの中では役に立たない。 – estus

+0

@estus bing mapsは以下のように呼び出されます: ''一度読み込まれると、上記のスニペットの 'Microsoft'にアクセスできます。これは、doc内のコントローラー内にのみ存在するように見えます。 – gardni

+0

APIを公開せずに可能であれば、フィーリング/ plunkとして問題を再現する方法を提供してくださいキーか何か。一般的に、答えは「あなたはangular.bootstrapで一度しか準備をしてはいけません」です。だから、特定のスクリプトとやりとりすることです。このAPI上に準備ができていることを確認するために接続できるイベントがある場合は、代わりにそれらを使用することを検討してください。 – estus

答えて

4

一般的に、角度アプリケーションは文書readyで既にブートストラップされています。これは自動ブートストラップのデフォルトの動作で、ng-appangular.bootstrapによる手動ブートストラップはreadyでも実行する必要があります。

質問は、現在のケース(MicrosoftのBing Maps API)に固有です。 ready is suggested by Microsoftを考慮すると、開発者はより優れた選択肢を持っています。

<script src="https://www.bing.com/api/maps/mapcontrol"></script> 

がsynchonouslyロードされているが、それは、最初の文書 readyがトリガされたときに、現時点ではまだロードされていないロードするために、依存関係の数をトリガします。実際には、 readyを別の readyの中に入れて初期化を完了する必要があります。これは元のコードとMicrosoftの例が示しているとおりであり、あまりうまく見えません。

競合状態を回避するために、アプリケーションのブートストラップは、すべての前提条件がロードされる瞬間、つまりwindow load event instead of document readyに延期することができます。それはかなりの遅延を提供することができるが、それは関係なく、それらの輸送がどのように行われるかの、アプリケーションが依存しているスクリプトがロードされたことを保証:

angular.element(window).on('load',() => { 
    angular.bootstrap(document.body, ['app'] 
}); 

APIは、初期化プロセスを制御するために提供することの代替はglobal callback function次のとおりです。

<script src="https://www.bing.com/api/maps/mapcontrol?callback=globalCallbackName"></script> 

コールバックではなく<script>に頼るのサービスでパックすることができます。

angular.module('bingMaps', []) 
.factory('bingMapsLoader', ($q, $window, $document, $timeout) => { 
    var script = document.createElement('script'); 
    script.src = 'https://www.bing.com/api/maps/mapcontrol?callback=bingMapsCallback'; 
    script.async = true; 

    $document.find('body').append(script); 

    return $q((resolve, reject) => { 
    $window.bingMapsCallback = resolve; 
    $timeout(reject, 30000); 
    }); 
}); 

bingMapsLoaderプロミスは、APIが初期化され、ルータリゾルバに入れられることを保証するためにチェーンすることができます。

さらに、コントローラのコンストラクタは、ディレクティブがコンパイルされる前に実行されます。サードパーティのAPIが使用されているか否か、角1.4および下に/ポストリンク機能を事前に、角1.5以上で$onInit又は$postLinkフックをコントローラにすべてのDOM固有のコードを移動する正しい:

app.controller('FooController', function (bingMapsLoader) { 
    this.$postLink =() => { 
    bingMapsLoader.then(() => this.mapsInit()); 
    }; 

    this.mapsInit =() => { 
    Microsoft.Maps.Map(...); 
    }; 
    ... 
+0

私は結局少し異なるアプローチをとったが、主な原則は答えに基づいており、コールバックをサービスに詰め込み、$ window.callbackを使用していた。あなたの努力に感謝します。 – gardni

関連する問題