使用promise使用ajax请求初始化服务数据?

时间:2014-01-06 14:20:38

标签: angularjs

我正在尝试使用AngularJS创建一个可以保存我网站购物车内容的服务。然后我将使用它来确保所有控制器中对购物车的引用应该是同一个对象并同步。

问题是必须通过ajax调用初始化购物车内容。我的下面的代码不起作用,但它显示了我想要完成的任务。我想以某种方式获取项目列表并使用getItems()返回,但如果尚未获取项目列表,那么我将首先获取它并承诺返回。我试图围绕“承诺”的概念,但到目前为止我还没有完全理解它。

factory('cartFactory', function ($rootScope, Restangular) {
    var cart = $rootScope.cart = {};

    return {
        getItems: function () {
            if (undefined == cart.items) {
                return Restangular.oneUrl('my.api.cart.show', Routing.generate('en__RG__my.api.cart.show')).get().then(function($cart){
                    cart = $rootScope.cart = $cart;

                    angular.forEach(cart.items, function(value, key){
                        cart.items[key]['path'] = Routing.generate('en__RG__my.frontend.product.info', {'slug': value.variant.product.slug});
                    });

                    return cart.items;
                });
            } else {
                return cart.items
            }
        },
        setItems: function ($items) {
            cart.items = $items;
        },
        removeItem: function ($item) {
            cart.splice(cart.indexOf($item), 1);
        },
        addItem: function ($item) {
            cart.items.push($item)
        }
    }
})

1 个答案:

答案 0 :(得分:1)

我将尝试以非常简单的方式解释这一点。

承诺只是一个“传递”的对象,我们使用这个对象来附加在我们解决,拒绝或通知承诺时将执行的函数。

因为在Javascript对象中通过引用传递,我们能够在几个地方引用同一个对象,在我们的例子中是服务和控制器。

在我们的服务中,我们执行:

getItems: function () {
    var deferred = $q.defer();

    // do async stuff

    return deferred.promise; 
}

让我们说上面推迟的变量是一个更像这样的对象:

{
  reject: function (reason) {
      this.errorCallback(reason);
  },
  resolve: function (val) {
      this.successCallback(val);
  },
  notify: function (value) {
      this.notifyCallback(value);
  },
  promise: {
      then: function (successCallback, errorCallback, notifyCallback) {
          this. successCallback = successCallback;
          this.errorCallback = errorCallback;
          this.notifyCallback = notifyCallback;
      }
  }
}

因此,当我们调用getItems()时,会返回一个promise(deferred.promise),这允许被调用者设置每当promise更改其状态(解析,拒绝或通知)时执行的回调。

所以在我们的控制器中我只设置了解析回调,如果拒绝它将会静默发生,因为没有要执行的errorCallback。

cartFactory.getItems().then(function (items) {
    $scope.items = items;
});

当然还有更多的背后,但我认为这种简单的承诺将帮助你获得基本的想法。请注意,cartFactory.getItems()必须始终返回一个promise,即使已经加载了这些项,否则cartFactory.getItems()。then()会在例如返回一个数组时中断。

使用cartFactory服务

Here a JSBin,我使用$ timeout来模拟异步调用。

希望这有帮助。