在数据上下文中的primeData调用中,有四个对后端Web API服务的查询:
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())依赖于模型。initialize——它依赖于第一个查询的结果(getLookups())。我想了解如何确保这种模式。在getlookup成功完成之前不会调用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
}
}]);
模型:
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;
}
}]);
创建一个返回promise的函数很简单:
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]);
}