3

在呈现视图之前,我在使用角度解析执行微风查询时遇到问题。我试图在用微风渲染视图之前从服务器获取一些数据。我在用着

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

控制器和服务片段:

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;
        }

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

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

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

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

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


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

如果有人可以帮助我,那就太好了。我不确定我是否做错了什么,或者 Q 承诺是否存在限制或解决方案轻而易举。

4

1 回答 1

6

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

但这不是真正的问题。真正的问题是 Angular 不知道您的异步方法何时解决。您必须$rootScope.$apply在成功和失败回调中手动调用。Angular 的 $http 和 $q 为您执行此操作(或等效项)。自己做对是一个 PITA。

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

简而言之,找一个靠近你的应用开始的地方,然后像这样扩展 Q:

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

功能实用程序($q,$rootScope){

   扩展Q();

   ...这里的其他实用程序...

   // Monkey patch to$q 方法到 Q.js 的 Promise 原型中
   // ex 用法:return manager.executeQuery(qry).to$q(succ, fail);
   函数扩展Q(){
       var promise = Q.defer().promise;
       var fn = Object.getPrototypeOf(promise);
       如果(fn.to$q)返回;// 已经扩展
       fn.to$q = 函数(成功,失败){
           返回 $q(this, 成功, 失败);
       };
   }

   函数 to$q(qPromise, 成功, 失败) {
       var d = $q.defer();
       qPromise
           .then(函数(数据){
               如果(数据 === 未定义){
                   logger.logError("编程错误:无数据。" +
                   "也许成功回调没有返回值或" +
                    "失败回调没有重新抛出错误");
                   // 如果一个错误被捕获并且没有在之前的承诺链中重新抛出
                   // 你会带着数据到达这里 === undefined。
                   // 忽略重新抛出是一种常见的意外遗漏。
                   // 为了安全起见,让每个成功回调返回一些东西
                   // 如果数据未定义,则在此处捕获
               }
               d.resolve(数据);
               $rootScope.$apply();// 见 https://groups.google.com/forum/#!topic/angular/LQoBCQ-V_tM
           })
          .失败(功能(错误){
              d.拒绝(错误);
              $rootScope.$apply();// 见 https://groups.google.com/forum/#!topic/angular/LQoBCQ-V_tM
          });

       如果(成功 || 失败){
           d.promise = d.promise.then(成功,失败);
       }
       返回 d.promise;
   }

现在像这样使用它(基于您的示例):

函数 getCountries() {

    var 查询 = 微风.EntityQuery.from("国家").orderBy("名称");

    返回 manager.executeQuery(query).to$q(getSucceeded);

    函数 getSucceeded(data) { return data.results; }
}

附录

我被问到:

为什么这么复杂?为什么不用$q.when(qPromse)Q promise转换成$q promise呢?

我试过了......但无法让它工作。具体来说,我试过这个:

函数 to$q(qPromise, 成功, 失败) {
    var 承诺 = $q.when(qPromise);
    如果(成功 || 失败){
       promise = promise.then(成功,失败);
    }
    回报承诺;
}

我相信有什么问题$q.when

于 2013-07-18T20:23:33.093 回答