长期.NET开发人员刚刚构建我的第一个Web应用程序。我试图使用Durandal,Breeze和Knockout,我认为我在架构上理解。然而,这并没有改变这样一个事实:我觉得我刚刚在国外登陆了jQuery的一些基本概念。
我在使用承诺的概念时使用Q进行异步编程时遇到问题。通常,在KO视图模型中,Durandal会有一个“激活”处理程序,其函数类似于
var activate = function() {
return ebodatacontext.getOrganizations(organizations);
};
其中调用Breeze datacontext以通过api从实体获取数据,而'organizations'是ko.observableArray。在我的应用程序中,这很好。
但是,在我的情况下,我的视图有两个实体列表,所以我需要两次调用datacontext,我和Q一起放在这里:
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
});
答案 0 :(得分:1)
我正在回答我自己的问题,因为我认为这个问题是由Q和承诺引起的。看来我的工作正常。
我的所有问题都通过在Breeze datacontext中意识到我需要使用data.result而不是数据初始化传入的ko.observableArray来解决。
我的破码:
var getOrganizations = function (organizationsObservable) {
var query = EntityQuery.from('Organizations');
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 getOrganizations = function (organizationsObservable) {
var query = EntityQuery.from('Organizations');
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
if (organizationsObservable) {
organizationsObservable(data.results);
}
log('Retrieved [Organizations] from remote data source',
data, true);
}
};
如果你和我一样陌生,那么线索就是当你观察到返回的ko.observableArray的内容时,它不应该是XHR类型的单个对象(呃duh)。从API调用返回到控制器的XHR在“结果”字段中具有实际日期。
感谢大家忍受新手尝试使用SPA客户端应用程序的所有最新技术。
好消息是,虽然我对某些基础知识仍然有点无能为力,但我正在努力拥有一个拥有完整数据生命周期和导航的富客户端,这看起来像一个专业网站(感谢bootstrap)。
我想通过他的Hot Towel模板向John Papa的Pluralsight课程和关于SPA应用程序的博客文章发表评论。