2

JavaScript ライブラリと AngularJS フロントエンドの両方を開発しています。JavaScript ライブラリは移植可能である必要があるため、AngularJS に依存することはできません。非常に標準的なサーブレット クエリ パターンを使用します。

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()、DB から返されたものを関数に表示させることはできません。コントローラーは次のとおりです。

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 を2番目ではなく最初のパラメーターとして取るように定義されているため、その文字列には $$phase プロパティがないため、 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;
        }
    };
});

元の例では、遅延を 2 回解決しています。safeApply 呼び出しで 1 回、コールバック関数で 1 回。Deferred は 1 回しか解決できないため (以降の呼び出しは無効)、deferred は safeApply で渡された値で解決されます。ほとんどの場合暗黙的に undefined を返すためqueryWrapperFor(ここでは定義が表示されません)、遅延は undefined で解決されます。

于 2013-07-24T03:04:46.077 に答える