Q - 在调用下一个操作之前等待操作完成

时间:2013-06-20 11:32:49

标签: javascript angularjs breeze q

在datacontext中的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())依赖于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;
    }



}]);

1 个答案:

答案 0 :(得分:3)

创建一个返回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]);
}