我正在开发一个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()
并获取一个promise对象。但无论我尝试什么,我都无法获取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);
});
})
我知道我错过了一些关于承诺如何运作的愚蠢但我看不清楚是什么。从我在代码中评论过的一些“选项”中可以清楚地看出,我只是在尝试随机方法并且交叉手指。
答案 0 :(得分:1)
首先要尝试修复此调用:
var promise = Data.getColNamesFromDb("table1", $scope);
根据您的示例,该方法被定义为将$ 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(我在这里看不到定义),因此你的deferred将使用undefined解决。