2013-04-17 21 views
9

我有一個使用Breeze的Angular應用程序,並且有一個用於我的不同控制器的共享EntityManager。可以在不執行查詢來預填充EntityManager的MetadataStore的情況下訪問我的一些控制器。我發現開始方向here表示在應用程序開始時獲取元數據。我的項目基於Angular-Breezejs模板,當我嘗試執行以下操作時,出現錯誤,因爲在使用datacontext之前,promise沒有完全解析。Breezejs,如何使用共享EntityManager開始獲取元數據

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 

在元數據提取完成之前阻塞的正確方法是什麼?由於似乎沒有必要在每個非查詢功能(包括實體創建)之前檢查元數據是否存在,如上面鏈接問題的原始海報最終所做的那樣。

回答

11

我看到你的問題。

當Angular調用您的工廠函數來創建DataContext服務時,它期望立即(同步)返回DataContext對象以準備使用。但是您將返回一個承諾在未來的某個時間返回DataContext ...而Angular並不是爲此而構建的。

雖然我喜歡這個主意。你可能想把它提交給Angular團隊:-)。

所以你在這裏嘗試只是不會工作。您必須立即返回DataContext。在元數據到達之前,您必須阻止整個UI或阻止依賴於元數據的特定功能(例如,createUser)。這有點像等待DOM在使用jQuery進行操作之前先解決掉。

這種情況並不是特定的。您在Knockout應用中面臨同樣的困境。決議是相似的。

首先暴露DataContext上某種「whenReady」鉤子。承諾可能是一個好主意。事情是這樣的:

 
function (breeze, Q, model, logger, $timeout) { 
    logger.log("creating datacontext"); 
    ... 
    var readyDeferred = Q.defer(), whenReady = readyDeferred.promise; 

    var datacontext = { 
      whenReady: whenReady, 
      ... 
     }; 

    initializeDatacontext(); 

    return datacontext; // now Angular is happy because it has a datacontext 

    function initializeDatacontext() { 
     manager.fetchMetadata() 
       .then(function() { 
        readyDeferred.resolve(); 
        // do success stuff; 
       }) 
       .fail(function (error) { 
        readyDeferred.reject(error); 
        // do error stuff; 
       }); 
    } 

    //Function definitions 
} 

別處在您的應用程序的引導,你扎入datacontext.whenReady承諾。

 
    // somewhere inside your main controller 
    $scope.isReady = false; 
    datacontext.whenReady.then(function() { 
      $scope.isReady = true; 
      $scope.$apply(); 
     }) 
    .fail(function() { alert("Uh oh!"); }); 
    ... 

現在綁定範圍的isReady到HTML,這樣你獲得所需的行爲。您可以使用它來阻止整個用戶界面,或者只是封閉功能(例如,「創建用戶」),直到datacontext準備就緒。

請勿逐字使用此僞代碼。用它來獲得靈感。

+0

這應該更新。 fetchMetadata需要一個Dataservice參數 – cecilphillip

+3

不,它不。你正在考慮'MetadataStore.fetchMetadata'。這是'EntityManager.fetchMetadata'。 – Ward