0

我正在使用库ParallelJS在网络工作者中进行加密/解密,但是当承诺得到解决时,它不会根据模型的更改更新视图。现在,我知道我必须将在 angularjs 范围之外调用的代码包装在 $scope.$apply 中,但即使这样做也无济于事。

我认为原因是我正在解析一个在 Angular 范围之外调用的回调中的延迟对象。这有点难以解释,所以让我展示我的代码:

function _encrypt(options){
... //crypto-js code to do AES encryption
}

function _decrypt(options){
... //crypto-js code to do AES decryption
}

angular.module('CryptoService', []).factory('Cryptor', function($q, $rootScope){
    function Cryptor(){};
    Cryptor.prototype = {
        encrypt: function(string, key) {
            var deferred = $q.defer();
            var ivS = generateIV();
            var p = new Parallel({
                iv: ivS,
                text: string,
                key: key
            }, { evalPath: '/assets/js/eval.min.js' });

            p.require('/assets/js/crypto.min.js');

            p.spawn(_encrypt).then(function(result){
                deferred.resolve(result);
            });

            return deferred.promise;
        },
        decrypt: function(string, key) {
            var deferred = $q.defer();
            var p = new Parallel({
                text: string,
                key: key
            }, { evalPath: '/assets/js/eval.min.js' });

            p.require('/assets/js/crypto.min.js');

            p.spawn(_decrypt).then(function(result){
                deferred.resolve(result);
            });
            return deferred.promise;
        }
    };
    return new Cryptor();
});

angular.module('ContactService', ['CryptoService']).factory('Contact', function($q, $rootScope, Cryptor){
    function Contact(){
        //initialization
    };
    Contact.prototype = {
       query: function(){
           var deferred = $q.defer();
           var options = {};
           _oauth.secureGET(this._endpoint,options).done(function(result){
               Cryptor.decrypt(result.cmc, key).then(function(string){
                   var data = JSON.parse(string);
                   var contacts = [];
                   for (var cidx in data){
                       var objContact = data[cidx];
                       var c = new Contact();
                       for(var pidx in this._properties){
                           var property = this._properties[pidx];
                           c[property] = objContact[property];
                       }
                       contacts.push(c);
                   }
                   //Since _oauth is using a jQuery method to execute the requests we are outside of angularjs' scope, so we need to wrap the promise resolution in 
                   //the $apply method of the rootscope
                   $rootScope.$apply(function(){
                       deferred.resolve(contacts);
                   });
               });

           }.bind(this)).fail(function() {
               $rootScope.$apply(function(){
                   deferred.resolve([]);
               });
           });
           return deferred.promise;
       },
   };
   return new Contact();
});

现在发生了什么:如果我离开代码,查询方法的回调函数永远不会被调用,因为在加密服务中,promise 在 angular 的范围之外被调用。如果我将 $rootScope.$apply 包装器移动到 Cryptor 服务,则调用 Contact 服务内的回调,调用控制器内的回调但视图未更新。

关于如何解决这个问题的任何提示?

谢谢大家

一个。

4

2 回答 2

1

好吧,我觉得很愚蠢......问题不在于视图没有更新,而是模型为空。由于我错过了bind(this)Cryptor 承诺的回调,模型是空的,视图没有显示任何内容。改变这个

Cryptor.decrypt(result.cmc, key).then(function(string){
    var data = JSON.parse(string);
    var contacts = [];
    for (var cidx in data){
        var objContact = data[cidx];
        var c = new Contact();
        for(var pidx in this._properties){
            var property = this._properties[pidx];
            c[property] = objContact[property];
        }
        contacts.push(c);
    }
    //Since _oauth is using a jQuery method to execute the requests we are outside of angularjs' scope, so we need to wrap the promise resolution in 
    //the $apply method of the rootscope
    $rootScope.$apply(function(){
        deferred.resolve(contacts);
    });
});

对此:

Cryptor.decrypt(result.cmc, key).then(function(string){
    ...
}.bind(this));

成功了。

于 2013-09-05T08:22:36.053 回答
0

从您的代码:

p.spawn(_encrypt).then(function(result){
    deferred.resolve(result); 
});

来自 Parallel.js 的 Promise 与 Angular.js 中的 Promise 不同。所以你需要包装

deferred.resolve(result);

进入 Angular.js $timeout:

$timeout(function(){
    deferred.resolve(result);
}, 0)

为了通知Angular.js

于 2013-09-04T13:07:12.343 回答