2

我正在开发一个 javascript 库和一个 AngularJS 前端。JavaScript 库需要是可移植的,所以它不能依赖 AngularJS。我们使用一个非常标准的 servlet 查询模式:

queryService = function(url, method, params, resultHandler, queryId)
{
  var request = {
    jsonrpc: "2.0",
    id: queryId || "no_id",
    method: method,
    params: params
   };
  $.post(url, JSON.stringify(request), handleResponse, "json");

  function handleResponse(response)
  {
    if (response.error)
        console.log(JSON.stringify(response, null, 3));
    else if (resultHandler)
        resultHandler(response.result, queryId);
   }
};

这个queryService函数被我们库中的其他函数调用。你可以看到它queryService什么也没返回。它期望回调函数执行所有需要的操作。我不知道需要什么回调函数才能将我的结果返回到 promise 对象的then()函数。这是 Angular 服务代码:

angular.module("app").service("Data", function($q){
return {
  getColNamesFromDb: function(table, scope){
    var deferred = $q.defer();

    var callbackFcn = function(result){
      console.log(result); // This successfully logs the result to the console!
      deferred.resolve(result); // also tried deferred.resolve();
    };

    var safeApply = function(scope, fn) {
      (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
    };
    safeApply(scope, function(){
      deferred.resolve(queryWrapperForColNames(scope.tableName, callbackfcn));
      // also tried $q.when(queryWrapperForColNames(scope.tableName, callbackfcn)); 
    });

    return deferred.promise;
  }};
});

从我的控制器中,我调用Data.getColNamesFromDb()并获得了一个承诺对象。但无论我尝试什么,我都无法让我的then()函数查看从数据库返回的内容。这是控制器:

angular.module("app").controller("Ctrl", function($scope, Data)
{
    $scope.options;

    var promise = Data.getColNamesFromDb("table1", $scope);

    promise.then(function(result){
        $scope.options = result;
    },function(result){
        console.log("error " + result);
    });
})

我知道我错过了关于承诺如何运作的一些愚蠢的东西,但我看不出是什么。从我在代码中评论的一些“选项”中应该可以清楚地看出,我只是在尝试随机方法并交叉手指。

4

1 回答 1

1

首先要尝试的是修复这个调用:

var promise = Data.getColNamesFromDb("table1", $scope);

根据您的示例,该方法被定义为将 $scope 作为第一个参数,而不是第二个参数,因此您的 safeApply 函数永远不会真正导致 $digest 循环发生,因为该字符串没有 $$phase 属性。

编辑

现在该示例已更正,请尝试以下操作:

angular.module( "app" ).service( "Data", function( $q ) {
    return {
        getColNamesFromDb: function( table, scope ) {
            var deferred = $q.defer();

            function safeApply( fn ) {
                if ( !scope.$$phase ) {
                    scope.$apply( fn );
                }
                else {
                    fn();
                }
            }

            queryWrapperForColNames( scope.tableName, function( result ) {
                safeApply(function() {
                    console.log( result );
                    deferred.resolve( result );
                });
            });

            return deferred.promise;
        }
    };
});

在您的原始示例中,您解决了两次延迟;一次在您的 safeApply 调用中,一次在您的回调函数中。Deferred 只能解析一次(进一步调用无效),因此 deferred 将使用 safeApply 中传递给它的值来解析。由于queryWrapperFor很可能隐式返回 undefined (我在这里看不到定义),因此您的 deferred 将使用 undefined 解决。

于 2013-07-24T03:04:46.077 回答