9

Breeze を使用する Angular アプリケーションがあり、異なるコントローラー用の共有 EntityManager があります。クエリを実行して EntityManager の MetadataStore を事前設定しなくても、いくつかのコントローラーにアクセスできます。ここで、アプリケーションの開始時にメタデータをフェッチするという開始方向をいくらか見つけました。私のプロジェクトは Angular-Breezejs テンプレートに基づいています。次のことをしようとすると、何かがデータコンテキストを使用する前に約束が完全に解決されないため、エラーが発生します。

app.factory('datacontext',
    ['breeze', 'Q', 'model', 'logger', '$timeout',
        function (breeze, Q, model, logger, $timeout) {
            logger.log("creating datacontext");

            configureBreeze();
            var manager = new breeze.EntityManager("/api/app");            
            manager.enableSaveQueuing(true);

            var datacontext = {
                metadataStore: manager.metadataStore,
                saveEntity: saveEntity,
                getUsers: getUsers,
                getUser: getUser,
                createUser: createUser,
                deleteUser: deleteUser
            };

            return manager.fetchMetadata()
                    .then(function () {
                        model.initialize(datacontext);
                        return datacontext;
                    })
                    .fail(function (error) {
                        console.log(error);
                        return error;
                    });
            //Function definitions

メタデータのフェッチが完了するまでブロックする適切な方法は何ですか? 上記のリンクされた質問の元の投稿者のように、各非クエリ関数 (エンティティの作成を含む) の前にメタデータが存在するかどうかを確認する必要はないようです。

4

1 に答える 1

11

私はあなたの問題を見ます。

DataContextAngular がファクトリ関数を呼び出して DataContext サービスを作成するとき、すぐに (同期的に)すぐに使用できるオブジェクトが返されることを期待します。しかし、あなたは将来のある時点でそれを返すという約束を返しています...そしてAngularはそのために構築されていません.DataContext

私はそのアイデアが好きです。Angular チームに提案することをお勧めします :-)。

したがって、ここで試みていることはうまくいきません。DataContextすぐに返さなければなりません。メタデータが到着するまで、UI 全体をブロックするか、メタデータに依存する特定の機能 (createUser など) をブロックする必要があります。jQuery で操作する前に、DOM が落ち着くのを待つようなものです。

この状況は Angular 固有のものではありません。Knockout アプリでも同じ問題に直面します。解像度は似ています。

DataContext である種の「whenReady」フックを公開することから始めます。約束はいい考えかもしれません。このようなもの:

関数 (ブリーズ、Q、モデル、ロガー、$timeout) {
    logger.log("データコンテキストの作成");
    ...
    var readyDeferred = Q.defer(), whenReady = readyDeferred.promise;

    var datacontext = {
            whenReady: いつ、
            ...
        };

    initializeDatacontext();

    データコンテキストを返します。// Angular は datacontext を持っているので満足です

    関数 initializeDatacontext() {
        manager.fetchMetadata()
               .then(関数 () {
                   readyDeferred.resolve();
                   // 成功する;
               }))
               .fail(関数 (エラー) {
                   readyDeferred.reject(エラー);
                   // エラー処理を行います。
               });
    }

    //関数定義
}

アプリのブートストラップの他の部分では、datacontext.whenReadypromise に結び付けます。

    // メインコントローラー内のどこか
    $scope.isReady = false;
    datacontext.whenReady.then(関数() {
           $scope.isReady = true;
           $scope.$apply();
       }))
    .fail(function() { alert("うーん!"); });
    ...

isReady目的の動作が得られるように、スコープを HTML にバインドします。これを使用して、データコンテキストの準備が整うまで、UI 全体をブロックするか、機能 (「ユーザーの作成」など) を単に封印することができます。

この疑似コードをそのまま使用しないでください。インスピレーションのためにそれを使用してください。

于 2013-04-17T20:47:03.530 に答える