当前位置: 首页 > 面试题库 >

服务是否应该公开其异步性?

楚宏胜
2023-03-14
问题内容

我正在编写一个将异步检索数据的服务($ http或$ resource)。我可以通过返回一个最初为空但最终将填充的数组来隐藏它是异步的事实:

.factory('NewsfeedService1', ['$http', function($http) {
   var posts = [];
   var server_queried = false;
   return {
      posts: function() {
         if(!server_queried) {
            $http.get('json1.txt').success(
              function(data) {
                server_queried = true;
                angular.copy(data, posts);
            });
         }
         return posts;
      }
   };
}])
.controller('Ctrl1', ['$scope','NewsfeedService1',
function($scope, NewsfeedService1) {
    $scope.posts = NewsfeedService1.posts();
}])

或者我可以通过返回一个承诺来暴露异步性:

.factory('NewsfeedService2', ['$http', function($http) {
  var posts = [];
  var server_queried = false;
  var promise;
  return {
     posts_async: function() {
       if(!promise || !server_queried) {
         promise = $http.get('json2.txt').then(
           function(response) {
              server_queried = true;
              posts = response.data;
              return posts;
         });
       }
       return promise;
     }
  };
}])

.controller('Ctrl2', ['$scope','NewsfeedService2',
function($scope, NewsfeedService2) {
  NewsfeedService2.posts_async().then(
    function(posts) {
      $scope.posts = posts;
  });
  // or take advantage of the fact that $q promises are
  // recognized by Angular's templating engine:
  // (note that Peter and Pawel's AngularJS book recommends against this, p. 100)
  $scope.posts2 = NewsfeedService2.posts_async();
}]);

(Plunker-如果有人想尝试上述两种实现。)

暴露异步性的一个潜在优势是,我可以通过向then()方法中添加错误处理程序来处理控制器中的错误。但是,我很可能会在应用程序范围的拦截器中捕获并处理$
http错误。

那么,什么时候应该暴露服务的异步性呢?


问题答案:

我的猜测是,您会在栅栏的两边找到人。 就个人而言 ,我认为您应该始终公开库或函数的异步性(或更正确地说:我认为您 永远 不应 隐藏
库或函数的异步性)。主要原因是透明度;例如,这行得通吗?

app.controller('MyController', function(NewsfeedService) {
  $scope.posts = NewsfeedService.posts();
  doSomethingWithPosts($scope.posts); // <-- will this work?
});

如果您使用第一种方法(例如$resource),即使$scope.posts从技术上讲它是一个数组,也不会。如果doSomethingWithPosts具有自己的异步操作,则可能会导致竞争。相反,您仍然必须使用异步代码:

app.controller('MyController', function(NewsfeedService) {
  $scope.posts = NewsfeedService.posts(function() {
    doSomethingWithPosts($scope.posts);
  });
});

(当然,您可以使回调接受posts作为参数,但是我仍然认为它令人困惑且不规范。)

幸运的是,我们有承诺,而承诺的真正目的是 代表 运营的未来价值。此外,由于$q可以使用Angular 库创建的Promise
绑定到视图,因此这没有错:

app.controller('MyController', function(NewsfeedService) {
  $scope.posts = NewsfeedService.posts();
  // $scope.posts is a promise, but when it resolves
  // the AngularJS view will work as intended.
});

[更新:您不再可以将Promise直接绑定到视图;您必须等待诺言得到解决,然后手动分配范围属性。]

顺便说一句,Restangular是的一种流行替代方法$resource,使用Promise,而AngularJS自己$resource将在1.2中支持它们(它们可能已经在最新的1.1.x中支持它们)。



 类似资料:
  • 问题内容: 我正在编写一个JavaScript函数,该函数发出HTTP请求并返回对结果的承诺(但该问题同样适用于基于回调的实现)。 如果我立即知道为该函数提供的参数无效,该函数应该同步还是应该返回被拒绝的Promise(或者,如果您愿意,请使用实例调用回调)? 异步功能应 始终 以异步方式运行(特别是对于错误情况)有多重要?是否确定,如果你知道程序是不是一个合适的状态的异步操作继续进行? 例如:

  • 我有多个线程使用ElasticSearchClient,如下所述 据我所知,Singleton类是线程安全的,但我不确定如果多个线程开始执行Singleton类的同一方法会发生什么。这有副作用吗? 注意:我知道上面的singleton类不是反射和序列化安全的。

  • 微丝网应该可重复使用吗?对于可重用,我并不意味着共享特定于域的模型。 我的意思是,为一个应用程序创建的微服务是否应该在另一个应用程序中重用?如果它们可以在应用程序中重用,是否足够? 分离微服务的最佳方法是什么。从我的观点来看,一旦一个微服务调用另一微服务,它就会紧密耦合,这意味着它不容易(无需修改)被提取并放入另一个没有它所引用/来自的相同服务的微服务应用程序中。 在我看来,要使它们脱钩,有以下几

  • 异步Tcp客户端 异步Http客户端 异步Redis客户端 异步Mysql客户端 异步Log日志 异步文件读写 异常Exception

  • 或者我可以使用一对服务器/客户端来处理同步请求,另一对来处理异步请求吗?我刚刚开始研究一个实现gRPC的分布式项目。我应该有多个数据库节点,每个都应该能够发送RPC到另一个。我必须同时允许同步和异步RPC。一个用于一般请求,另一个用于两阶段提交。但是gRPC教程没有提到我是否应该将两个服务合并到一台服务器中,并将它们分开。谢谢

  • 异步Log日志 use AsyncLog; yield AsyncLog::info('hello world'); yield AsyncLog::debug('test debug', ['foo' => 'bar']); yield AsyncLog::notice('hello world',[], 'group.com'); yield Async