2013-07-24 25 views
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什麼都沒有返回。它期望回調函數執行所有需要的操作。我不知道需要什麼回調函數才能將結果返回到承諾對象的then()函數。這裏的角服務代碼:

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

我知道我缺少有關的承諾是如何工作的一些愚蠢的事,但我什麼也看不見。從我在代碼中評論過的一些「選項」中應該可以清楚地看出,我只是在嘗試使用隨機方法並穿過我的手指。

回答

1

是嘗試解決這個呼叫的第一件事:

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

根據你的榜樣,該方法被定義爲以$範圍作爲第一個參數,而不是第二個,所以你safeApply功能不會真正由於該字符串沒有$$階段屬性,因此會導致發生$ digest循環。

編輯

現在的例子已得到糾正,試試這個:

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調用中,一次在您的回調函數中。延遲只能解析一次(進一步的調用沒有效果),所以延遲將通過safeApply傳遞給它的值來解決。由於queryWrapperFor很可能隱含地返回undefined(我在這裏沒有看到這個定義),所以你的延期將被解析爲undefined。

+0

你說得對。發佈時,我意外地刪除了'getColNamesFromDb()'的第一個參數。我通過添加一個'table'參數來糾正參數匹配。 – PatchCR

+0

謝謝!這工作!有一件事我不明白的是你的'safeApply'如何在不明確傳入的情況下引用正確的'scope'。 – PatchCR

+0

'scope'變量已經被傳遞到getColNamesFromDb函數中,所以它在safeApply函數中可用,因爲它仍然在函數的作用域中。 – dherman