使用$ route resolve停止页面解析breeze query/Q promise

Haw*_*awk 3 angularjs breeze q

在呈现视图之前,我在使用angular resolve执行breeze查询时遇到问题.在使用breeze渲染视图之前,我正试图从服务器获取一些数据.我正在使用

$routeProvider.when('/countries', { templateUrl: 'App/partials/countries.html', controller: Ctrl, resolve: Ctrl.resolve }).
Run Code Online (Sandbox Code Playgroud)

控制器和服务片段:

function Ctrl($scope, Q, datacontext, countries) {

//...

}

function getCountries(forceRefresh) {

            var query = entityQuery.
                from("countries").
                orderBy("name");

            return manager.executeQuery(query).
            then(getSucceeded);

        }

        function getSucceeded(data) {
            return data.results;
        }
Run Code Online (Sandbox Code Playgroud)

这使我的视图永远不会呈现:

Ctrl.resolve = {
    countries: function (datacontext) {
        return datacontext.getCountries();
    }
}
Run Code Online (Sandbox Code Playgroud)

而如果我创建一个需要更长时间的计时器,它就可以工作.我尝试用$ q包装它,但我似乎无法让它工作.

由于超时,这将呈现视图:

Ctrl.resolve = {
    countries: function (datacontext) {
        return datacontext.getCountries();


    },
    delay: function ($q, $timeout) {
        var delay = $q.defer();
        $timeout(delay.resolve, 6000);
        return delay.promise;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有人能帮助我,那就太好了.我不确定我是做错了什么,或者Q承诺或微风的限制.

War*_*ard 6

我感觉到你的痛苦.$ q/route resolve实现中的一个错误是解析不遵守该Q.then方法.这违反了普遍接受的支持可互换承诺实施(叹息)的做法.

但这不是真正的问题.真正的问题是Angular不知道何时解析了异步方法.您必须$rootScope.$apply在成功和失败回调中手动调用.Angular的$ http和$ q为你做这个(或等价).自己做对了就是PITA.

正如我所说,我们感受到你的痛苦.很快我们将发布一个小Q插件,将Q承诺转换为$ q承诺,并应该减轻这种痛苦.至少它对我有用:-).

简而言之,找到一个靠近应用程序启动位置的地方并扩展Q,如下所示:

angular.module('app').factory('util', ['$q', '$rootScope', util]);

function util($q, $rootScope) {

   extendQ();

   ... other utilities here ...

   // Monkey patch to$q method into Q.js' promise prototype
   // ex usage: return manager.executeQuery(qry).to$q(succ, fail);
   function extendQ() {
       var promise = Q.defer().promise;
       var fn = Object.getPrototypeOf(promise);
       if (fn.to$q) return; // already extended
       fn.to$q = function (success, fail) {
           return to$q(this, success, fail);
       };
   }

   function to$q(qPromise, success, fail) {
       var d = $q.defer();
       qPromise
           .then(function (data) {
               if (data === undefined) {
                   logger.logError("Programming error: no data. " +
                   "Perhaps success callback didn't return a value or " +
                    "fail callback didn't re-throw error");
                   // If an error is caught and not re-thrown in an earlier promise chain
                   // you will arrive here with data === undefined. 
                   // Neglecting to re-throw is a common, accidental omission.
                   // To be safe, have every success callback return something
                   // and trap here if data is ever undefined
               }
               d.resolve(data);
               $rootScope.$apply();// see https://groups.google.com/forum/#!topic/angular/LQoBCQ-V_tM
           })
          .fail(function (error) {
              d.reject(error);
              $rootScope.$apply();// see https://groups.google.com/forum/#!topic/angular/LQoBCQ-V_tM
          });

       if (success || fail) {
           d.promise = d.promise.then(success, fail);
       }
       return d.promise;
   }

现在使用它(基于你的例子):

function getCountries() {

    var query = breeze.EntityQuery.from("countries").orderBy("name");

    return manager.executeQuery(query).to$q(getSucceeded);

    function getSucceeded(data) { return data.results; }
}

附录

我被问到:

" 为什么这么复杂?你为什么不用$q.when(qPromse)Q转换给$ q诺? "

我试过了......并且无法使其发挥作用.具体来说,我试过这个:

function to$q(qPromise, success, fail) {
    var promise = $q.when(qPromise);
    if (success || fail) {
       promise = promise.then(success, fail);
    }
    return promise;
}

我相信有一些问题$q.when.