【问题标题】:Angular promise then callback not firing on chrome.storage.local.getAngular 承诺然后回调不会在 chrome.storage.local.get 上触发
【发布时间】:2013-01-13 14:04:22
【问题描述】:

我只是在玩 angular 及其 DI。我也尝试使用 Promise 范式,但是在 Chrome 扩展程序中使用它时遇到了一个相当奇怪的问题。

以下代码运行良好。当调用“chromeStorageService”中的对象字面量中的 cb() 时,promise 就解决了。 但是当我取消注释返回 chrome.storage.local; 时,代码停止工作。我不明白为什么,因为console.log('going to be resolved'); 仍然被解雇,但成功警报却没有。提前感谢任何提示:)

http://jsfiddle.net/Ku5dz/

https://developer.chrome.com/extensions/storage.html

'use strict';
var app = {};

app = angular.module('options', ['options.controllers']);

app.services = angular.module('options.services', []);


app.services.factory('chromeStorageService', function () {
    //return chrome.storage.local;


    return {
        get: function(id, cb) {
            cb();
        }
    }
});

app.services.factory('storageService', ['chromeStorageService', '$q', function (chromeStorage, $q) {
    return new function () {
        this.get = function (identifier) {
            var defered = $q.defer();

            chromeStorage.get(identifier, function (items) {
                var error = false//chrome.runtime.lastError;
                if (error) {
                    return defered.reject(error);
                }

                console.log('going to be resolved');
                console.log(defered);
                defered.resolve();
            });

            return defered.promise;
        }
    }
}]);

app.services.factory('fooService', ['storageService', function (testService) {
    return new function () {
        this.getAll = function () {
            var promise = testService.get('foo');
            console.log(promise);
            promise.then(
                function () {
                    alert('success');
                }, function () {
                    aler('err');
                }
            );
        }
    }
}]);


app.directive('foo', ['fooService', function (fooService) {
    return {
        restrict:'A',
        link:function (scope, elm, attrs, ctrl) {
            fooService.getAll();    
        }
    };
}]);


app.controllers = angular.module('options.controllers', ['options.services']);

【问题讨论】:

    标签: javascript dependency-injection google-chrome-extension angularjs


    【解决方案1】:

    如果你在 get 之前取消注释 return ,除了 get 调用之外你怎么做??

    基本上,只要您返回“某物”,您就会失去功能

    在 Angular js 中,您可以使用以下语法调用 then 函数

        $http.get(url).then(function(response){
               //put your callback code here
           }) 
    

    【讨论】:

    【解决方案2】:

    基本上,您的代码未运行的原因是因为您正在返回 chrome.local.storage,这会将您带出范围,并且 get 函数永远没有机会执行。请参阅 chrome API 的操作方法,它与 angular 的 $http 服务非常相似

    【讨论】:

      【解决方案3】:

      Angular 有自己的小事件循环。当你 .resolve 一个承诺时,它会进入 Angular 的队列。只有当 Angular 清除它的队列时,事情才会发生。

      通常的做法是:

      $scope.$apply(function() {
        promise.resolve(thing);
      });
      

      当控制权从您传递给它的函数返回到 $apply 时,它会清除队列,一切都很美好。在这种情况下,您可能需要将 $rootScope 注入到服务中,以便根据The view is not updated in AngularJS 应用一些东西。

      您的存根可以正常工作,因为存根永远不会离开角度世界,因此您已经处于处理队列的上下文中。当您使用 chrome.storage.local 时,您的回调不会从这样的上下文中调用。

      【讨论】:

      • 我遇到了同样的问题:在 $scope 中调用一个从指令返回承诺的函数没有触发指令中的 then()。令我惊讶的是——你的把戏真的奏效了。我将 resolve() 和 reject() 包裹在 $apply 中,一切运行良好。您是否参考了解释原因的文档?我觉得这很丑陋,并想确保在将 $q 与 Angular 一起使用时我不会做一些不自然的事情。也许我不应该从指令调用延迟函数到 $scope?
      • 谢谢,这篇文章很好。我认为我的问题与其说是延迟实现本身,不如说是我在非 Angular 异步回调中解决它的事实(我很懒惰并使用 $.ajax 来安慰)。我将尝试切换到 Angular 等效项,我希望它将我的回调包装到 $scope.$apply() 中并简化我的语法。
      【解决方案4】:

      我今天遇到了同样的问题。我想将 chrome.storage.local.get 与 Angular 承诺模式集成,因为 chrome.storage.local.get 是异步函数。我就是这样做的:

      // service
      angular.module('app').factory('STORAGE', function($q) {
          return {
              get: function(key) {
                  var deferred = $q.defer();
      
                  chrome.storage.local.get(key, function(data) {
                      deferred.resolve(data[key]);
                  });
      
                  return deferred.promise;
              },
              set: function(key, value) {
                  var deferred = $q.defer();
      
                  var data = {};
                  data[key] = value;
                  chrome.storage.local.set(data, function() {
                      deferred.resolve({});
                  });
      
                  return deferred.promise;
              },
              del: function(key) {
                  var deferred = $q.defer();
      
                  chrome.storage.local.remove(key, function() {
                      deferred.resolve({});
                  });
      
                  return deferred.promise;
              }
          }
      });
      

      我定义了一个 Angular 服务调用 STORAGE,我可以封装 chrome.storage.local。 getsetdel 方法。

      然后我们可以将STORAGE 注入到Angular 路由resolve 部分

      // route resolve
      ...
      resolve: {
          hasToken: function(STORAGE) {
              return (STORAGE.get('instagram_access_token')) ? true : false;
          }
      }
      ...
      

      向控制器注入路由解析参数和STORAGE

      // controller 
      angular.module('app').controller('HomeController', ['$scope', 'hasToken', 'STORAGE',
          function($scope, hasToken, STORAGE) {
              $scope.hasToken = hasToken;
      
              if ($scope.hasToken) {
                  STORAGE.get('profile').then(function(data) {
                      $scope.user = data;
                  });
              }
          }
      ]);
      

      效果很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-07
        • 2022-01-04
        • 1970-01-01
        相关资源
        最近更新 更多