2013-06-20 33 views
1

內primeData電話有四種查詢到後端的Web API服務之前完成:Q - 等待操作的DataContext調用接下來的操作

function primeData(forceRefresh) { 
    return (getLookups(forceRefresh) // this needs to complete before moving on 
       .then(success)) 
       .then(model.initialize(datacontext)) // depends on getLookups 
       .then(getDatasetOne()) // depends on model.initialize 
       .then(getDataSetTwo()) // depends on model.initialize 
       .then(getNonDependantDataset); // doesn't depend on previous calls 

    function success(data) { 

     if (!initialized) { 
     datacontext.lookups = data.results[0]; 
     initialized = true; 
     } else { 
     datacontext.lookups = { 
      teams: getLocal('Teams', 'id'), 
      // other lookup values here      
      }; 
     } 
     // should I call model.initialize(datacontext) here?? 
    } 
} 

查詢2和3(getDatasetOne()和getDatasetTwo ())依賴於model.initialize - 這取決於第一個查詢(getLookups())的結果。我想知道如何確保在getLookups成功完成之前不調用model.initialize - 並確保在模型初始化之前不調用getDatasetOne/Two。儘可能減少/簡化代碼以顯示完整圖片。顯然,我不明白Q.任何援助將不勝感激。

控制器:

'use strict'; 

app.controller('HomeController', 
    ['$scope', 'breeze', 'datacontext', 'logger', 
    function HomeController($scope, breeze, datacontext, logger) { 

     function initialize(forceRefresh) { 
      datacontext.initialize(forceRefresh) 
       .then(getSucceeded) 
       .fail(queryFailed) 
       .fin(refreshView); 
     } 

     initialize(); 

     $scope.refresh = refresh; 

     function refresh() { 
      initialize(true); 
     } 

     function getSucceeded() { 
      $scope.lookups = datacontext.lookups; 
      $scope.datasetOne = datacontext.datasetOne; 
      $scope.datasetTwo = datacontext.datasetTwo; 
     } 

     function refreshView() { 
      $scope.$apply(); 
     } 

     function queryFailed(error) { 
      logger.error(error); 
     }  
    }]); 

的DataContext:

app.factory('datacontext', 
    ['breeze', 'Q', 'logger', 'model', 
    function (breeze, q, logger, model) { 

     var initialized; 

     var manager = configureBreezeManager(); 

     var datacontext = { 
      initialize: initialize, 
      metadataStore: manager.metadataStore, 
      saveEntity: saveEntity 
     }; 

     return datacontext; 

     //#region private members 

     function initialize(forceRefresh) { 
      if (!initialized || forceRefresh) { 
       return primeData(forceRefresh).then(function() { 
        logger.log("Running Initialize"); 
       }); 
      } else { 
       logger.log("Already Initialized"); 
       return q(); 
      } 
     } 

     function primeData(forceRefresh) { 

      return (getLookups(forceRefresh) 
       .then(success)) 
       .then(model.initialize(datacontext)) 
       .then(getDatasetOne()) 
       .then(getDataSetTwo()) 
       .then(getNonDependantDataset); 

      function success(data) { 

       if (!initialized) { 
        datacontext.lookups = data.results[0]; 
        initialized = true; 
       } else { 
        datacontext.lookups = { 
         teams: getLocal('Teams', 'id'), 
         // other lookup values here      
        }; 
       } 
       // should I call model.initialize(datacontext) here?? 
      } 
     } 

     function getLookups(forceRefresh) { 
      var query = breeze.EntityQuery 
       .from('Lookups'); 

      if (initialized && !forceRefresh) { 
       return true; 
      } 
      return manager.executeQuery(query); 
     } 

     function getDatasetOne() { 
      var query = breeze.EntityQuery 
       .from("EntityNameOne"); 
      return manager.executeQuery(query).then(getSucceeded); 

      function getSucceeded(data) { 
       datacontext.datasetOne = model.process(data.results) 
       return q(); 
      } 
     } 

     function getDatasetTwo() { 
      var query = breeze.EntityQuery 
       .from("EntityNameTwo"); 
      return manager.executeQuery(query).then(getSucceeded); 

      function getSucceeded(data) { 
       datacontext.datasetTwo = model.process(data.results); 
       return q(); 
      } 
     } 

     function getNonDependentDataset() { 
      var query = breeze.EntityQuery 
       .from('EntityNameThree'); 

      return manager.executeQuery(query).then(success); 

      function success(data) { 
       datacontext.nonNependentDataset = data.results; 
      } 
     } 

     function saveEntity(masterEntity, message) { 
      // standard implementation 
     } 

     function getLocal(resource, ordering) { 
      var query = breeze.EntityQuery.from(resource) 
       .orderBy(ordering); 
      return manager.executeQueryLocally(query); 
     } 

     function configureBreezeManager() { 
      // standard implementation 
     } 
    }]); 

MODEL:

app.factory('model', ['logger', function (logger) { 

    var datacontext; 
    extendDatasetOne(); 
    extendDatasetTwo(); 

    var model = { 
     initialize: initialize, 
     getDatasetOne: getDatasetOne, 
     getDatasetTwo: getDatasetTwo 
    }; 

    return model; 

    function initialize(context) { 
     datacontext = context;   
    } 

    function getDatasetOne(input) { 
     var ret = []; 
     for (var i = 0; i < input.length; i++) { 
      var item = new TypeOne(input[i]); 
      ret.push(item); 
     } 
     return ret; 
    } 

    function getDatasetTwo(input) { 
     var ret = []; 
     for (var i = 0; i < input.length; i++) { 
      var item = new TypeTwo(input[i]); 
      ret.push(item); 
     } 
     return ret; 
    } 

    function TypeOne(item) { 
     var self = this; 

     for (var prop in item) { 
      if (item.hasOwnProperty(prop)) { 
       self[prop] = item[prop]; 
      } 
     } 

     self.name = getNameForId(item.id); 
    } 

    function TypeTwo(item) { 
     var self = this; 

     for (var prop in item) { 
      if (item.hasOwnProperty(prop)) { 
       self[prop] = item[prop]; 
      } 
     } 

     self.name = getNameForId(item.id); 
    } 

    function extendDatasetOne() { 
     // add properties to prototype 
    } 

    function extendDatasetOne() { 
     // add properties to prototype 
    } 

    function getNameForId(id) { 
     var set = datacontext.lookups.items; 
     for (var i = 0; i < set.length; i++) { 
      if (id == set[i].id) { 
       return set[i].name; 
      } 
     } 
     return null; 
    } 



}]); 

回答

3

要創建返回一個承諾的功能很簡單:

function test() { 
    var defer = Q.defer(); 
    // an example of an async call 
    serverCall(function (request) { 
     if (request.status === 200) { 
      defer.resolve(request.responseText); 
     } else { 
      defer.reject(new Error("Status code was " + request.status)); 
     } 
    }); 
    return defer.promise; 
} 

現在,您可以將它與.then()一起使用。

下面是如何可以工作,你primeData函數的一個例子:

function primeData(forceRefresh) { 
    function success(data) { 
     if (!initialized) { 
     datacontext.lookups = data.results[0]; 
     initialized = true; 
     } else { 
     datacontext.lookups = { 
      teams: getLocal('Teams', 'id'), 
      // other lookup values here      
      }; 
     } 
    } 

    var getLookupsPromise = getLookups(forceRefresh); 

    // .then method returns a new promise. 
    var successPromise = getLookupsPromise.then(success); 
    // success is called when the getLookupsPromise promise is resolved 
    // Now success promise will resove when succes code is resoved. 
    // If success where assync and it returned an other promise this will resolve when the promise resolves. 

    var modelInitializePromise = getLookupsPromise.then(function() { 
     model.initialize(datacontext); 
    }); 

    var datasetOnePromise = modelInitializePromise.then(getDatasetOne); 
    var datasetTwoPromise = modelInitializePromise.then(getDatasetTwo); 

    var nonDependantPromise = getNonDependantDataset(); 

    // Generate a promise that will resolve when all promises are resolved 
    return q.all([getLookupsPromise, successPromise, modelInitializePromise, 
     datasetOnePromise, datasetTwoPromise, nonDependantPromise]); 
}