Angular HTTP 承诺中的竞争条件

Race condition in Angular HTTP promises

所以,我有一个小的 API 交互代码,如下所示:

function load_posts() {
  return $http
    .get('/posts')
    .then(on_success);

  function on_success(response) {
    return response.data;
  }
}

function get_posts() {
  if (blog.posts) {
    return $q.when(blog.posts);
  }

  return load_posts().then(function (posts) {
    blog.posts = posts;

    return blog.posts;
  });
}

我这样做是为了避免一直点击 API 以获得相同的结果。我有几个单独的指令和组件可能需要调用此 API 端点,但它们不需要每次都有新的结果。但这会导致丑陋的竞争条件:如果两个或多个组件在 load_posts 响应到达之前调用 get_posts 方法,那么它们都会发出 API 请求。没有副作用,因为这只是一次缓存尝试,但它破坏了整个目的。

关于如何处理这个问题有什么想法吗?

这并不是真正的竞争条件问题,只是记忆函数的问题。您可以使用 Underscore.js 中的 memoize() 之类的东西,或者自己实现它:

var load_posts = () => {
  const p = $http
    .get('/posts')
    .then(response => response.data);
  load_posts = () => p;
  return p;
};

$http 服务可以缓存请求。 See here or the docs 更深入地解释缓存的工作原理。

The default $http cache can be particularly useful when our data doesn’t change very often. We can set it like so:

$http({
  method: 'GET',
  url: '/api/users.json',
  cache: true
});
// Or, using the .get helper
$http.get('/api/users.json', {
  cache: true
});

Now, every request that is made through $http to the URL /api/users.json will be stored in the default $http cache. The key for this request in the $http cache is the full-path URL.

1) 将数据检索提取到单独的 "blogService" 服务中;

2) 在执行请求的服务中缓存承诺;

3) Return 对所有客户端的相同承诺,如果您不想公开整个响应对象,您可以操纵结果;

var promise = null;

function loadBlogs() {
    promise = promise || $http.get("/posts").then(function(response){return reponse.data;});
    return promise;
}

4) 然后只需调用服务方法并等待 promise 在您需要的任何地方解析(控制器、指令等):

function getPosts() {
    blogService.loadBlogs().then(function (posts) {
        vm.posts = posts;
  });