长期 .NET 开发人员刚刚构建了我的第一个 Web 应用程序。我正在尝试使用我认为我在架构上理解的 Durandal、Breeze 和 Knockout。然而,这并没有改变这样一个事实,即我觉得我只是带着一些 jQuery 的基本概念来到了异国他乡。
我在使用 Q 的 Promise 概念进行异步编程时遇到了问题。通常,在 KO 视图模型中会有一个用于 Durandal 的“激活”处理程序,其功能如下:
var activate = function() {
return ebodatacontext.getOrganizations(organizations);
};
其中调用 Breeze 数据上下文以通过 api 从实体获取数据,并且“组织”是 ko.observableArray。在我的应用程序中,这工作正常。
但是,在我的情况下,我的视图有两个实体列表,因此我需要对我与 Q 放在一起的 datacontext 进行两次调用,如下所示:
var activate = function() {
var promise =
Q.all([
ebodatacontext.getOrganizations(organizations),
ebodatacontext.getUserRoles(userRoles)
]);
return promise;
};
据我所知,这些 datacontext 调用中的任何一个都可以自行工作并将 ok 绑定到视图。但是当他们像这样智商时,似乎只有第一个有效。我担心我在这里遗漏了一些基本的东西。
我可以在网络流量中看到两个 api 调用都是针对两组实体进行的。并通过网络返回良好的结果。
但是,似乎第二次调用的 ko.observable (userRoles) 并没有以任何数据结束。如果我交换它们的顺序,在 Q 数组中,第一个有效。在我看来,我在这里忽略了一些东西,并且绑定发生得太快了。
如果我在这里使用的 Q 是正确的,我会假设我在其他地方还有更多的调试要做。提前致谢。
这是使用 Breeze 的 ebodatacontext:
define([
'durandal/system',
'services/ebomodel',
'config',
'services/logger'],
function (system, ebomodel, config, logger) {
var EntityQuery = breeze.EntityQuery;
var manager = configureBreezeManager();
var orderBy = ebomodel.orderBy;
var entityNames = ebomodel.entityNames;
var getOrganizations = function(organizationsObservable, forceRemote) {
if (!forceRemote) {
var p = getLocal('Organizations', orderBy.Name);
if (p.length > 0) {
organizationsObservable(p);
return Q.resolve();
}
}
var query = EntityQuery.from('Organizations')
//.orderBy(orderBy.Name)
;
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
if (organizationsObservable) {
organizationsObservable(data);
}
log('Retrieved [Organizations] from remote data source',
data, true);
}
};
var getUserRoles = function(rolesObservable, forceRemote) {
if (!forceRemote) {
var p = getLocal('UserRoles', orderBy.Name);
if (p.length > 0) {
rolesObservable(p);
return Q.resolve();
}
}
var query = EntityQuery.from('UserRoles')
// .orderBy(orderBy.Name)
;
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
if (rolesObservable) {
rolesObservable(data);
}
log('Retrieved [UserRoles] from remote data source',
data, true);
}
};
var cancelChanges = function() {
manager.rejectChanges();
log('Canceled changes', null, true);
};
var saveChanges = function() {
return manager.saveChanges()
.then(saveSucceeded)
.fail(saveFailed);
function saveSucceeded(saveResult) {
log('Saved data successfully', saveResult, true);
}
function saveFailed(error) {
var msg = 'Save failed: ' + error.message;
logError(msg, error);
error.message = msg;
throw error;
}
};
var primeData = function () {
};
var createOrganization = function() {
return manager.createEntity(entityNames.organization);
};
var createUserRole = function() {
return manager.createEntity(entityNames.role);
};
var hasChanges = ko.observable(false);
manager.hasChangesChanged.subscribe(function(eventArgs) {
hasChanges(eventArgs.hasChanges);
});
var ebodatacontext = {
createOrganization: createOrganization,
createUserRole: createUserRole,
getOrganizations: getOrganizations,
getUserRoles: getUserRoles,
hasChanges: hasChanges,
primeData: primeData,
cancelChanges: cancelChanges,
saveChanges: saveChanges
};
return ebodatacontext;
//#region Internal methods
function getLocal(resource, ordering, includeNullos) {
var query = EntityQuery.from(resource)
// .orderBy(ordering)
;
//if (!includeNullos) {
// query = query.where('id', '!=', 0);
//}
return manager.executeQueryLocally(query);
}
function queryFailed(error) {
var msg = 'Error retreiving data. ' + error.message;
logger.logError(msg, error, system.getModuleId(ebodatacontext), true);
throw error;
}
function configureBreezeManager() {
breeze.NamingConvention.camelCase.setAsDefault();
var mgr = new breeze.EntityManager(config.eboRemoteServiceName);
ebomodel.configureMetadataStore(mgr.metadataStore);
return mgr;
}
function log(msg, data, showToast) {
logger.log(msg, data, system.getModuleId(ebodatacontext), showToast);
}
//#endregion
});