我是否正确使用Q与Durandal,KO和Breeze?

时间:2013-05-20 20:30:36

标签: knockout.js breeze durandal q

长期.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
});

1 个答案:

答案 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应用程序的博客文章发表评论。

http://www.johnpapa.net/hottowel/