如何使用 $q 从 AngularJS 服务返回已解决的承诺?

     2023-02-22     64

关键词:

【中文标题】如何使用 $q 从 AngularJS 服务返回已解决的承诺?【英文标题】:How to return a resolved promise from an AngularJS Service using $q? 【发布时间】:2014-06-27 08:38:21 【问题描述】:

我的服务是:

myApp.service('userService', [
  '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) 
    var deferred;
    deferred = $q.defer();
    this.initialized = deferred.promise;
    this.user = 
      access: false
    ;
    this.isAuthenticated = function() 
      this.user = 
        first_name: 'First',
        last_name: 'Last',
        email: 'email@address.com',
        access: 'institution'
      ;
      return deferred.resolve();
    ;
  
]);

我在我的config 文件中通过以下方式调用它:

myApp.run([
  '$rootScope', 'userService', function($rootScope, userService) 
    return userService.isAuthenticated().then(function(response) 
      if (response.data.user) 
        return $rootScope.$broadcast('login', response.data);
       else 
        return userService.logout();
      
    );
  
]);

但是,它抱怨then 不是一个函数。我不是在返回已解决的承诺吗?

【问题讨论】:

【参考方案1】:

如何在 AngularJS 中简单地返回一个预先解决的承诺

已解决的承诺:

return $q.when( someValue );    // angularjs 1.2+
return $q.resolve( someValue ); // angularjs 1.4+, alias to `when` to match ES6

被拒绝的承诺:

return $q.reject( someValue );

【讨论】:

这正是我想要的。存根 http 服务调用时返回静态值的好方法。【参考方案2】:

返回你的承诺,返回 deferred.promise。 它是具有 'then' 方法的 promise API。

https://docs.angularjs.org/api/ng/service/$q

调用 resolve 不会返回一个 Promise,它只会发出信号 承诺承诺已解决,因此它可以执行'then'逻辑。

基本模式如下,冲洗一遍重复http://plnkr.co/edit/fJmmEP5xOrEMfLvLWy1h?p=preview

<!DOCTYPE html>
<html>

<head>
  <script data-require="angular.js@*" data-semver="1.3.0-beta.5" 
        src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body>

<div ng-controller="test">
  <button ng-click="test()">test</button>
</div>
<script>
  var app = angular.module("app",[]);

  app.controller("test",function($scope,$q)

    $scope.$test = function()
      var deferred = $q.defer();
      deferred.resolve("Hi");
      return deferred.promise;
    ;

    $scope.test=function()
      $scope.$test()
      .then(function(data)
        console.log(data);
      );
          
  );

  angular.bootstrap(document,["app"]);

</script>

【讨论】:

那么承诺将如何解决? .then 永远不会被触发 @Shamoon deferred.resolve();在您调用它的那一刻就解决了,因为没有给出任何值。我建议不要写 deferred.resolve("Hi");只需编写 deferred.resolve();得到一个已解决的空头承诺。但你也可以使用 $q.when();得到一个可解决的空承诺;-)。 恕我直言,这比接受的答案要好,后者通过使用 $timeout 生成将要解决的承诺无法显示手动创建和解决承诺的机制。【参考方案3】:

要返回已解决的承诺,您可以使用:

return $q.defer().resolve();

如果您需要解决某些问题或返回数据:

return $q.defer().resolve(function()

    var data;
    return data;

);

【讨论】:

我有 posted 一个更短的版本。【参考方案4】:

对于较短的 JavaScript 代码,请使用:

myApp.service('userService', [
  '$q', function($q) 
    this.initialized = $q.when();
    this.user = 
      access: false
    ;
    this.isAuthenticated = function() 
      this.user = 
        first_name: 'First',
        last_name: 'Last',
        email: 'email@address.com',
        access: 'institution'
      ;
      return this.initialized;
    ;
  
]);

您知道您通过用新对象覆盖而不是仅设置对象属性来解除与 userService.user 的绑定吗?

以下是我的 plnkr.co 示例代码示例(工作示例: http://plnkr.co/edit/zXVcmRKT1TmiBCDL4GsC?p=preview):

angular.module('myApp', []).service('userService', [
    '$http', '$q', '$rootScope', '$location', function ($http, $q, $rootScope, $location) 
    this.initialized = $q.when(null);
    this.user = 
        access: false
    ;
    this.isAuthenticated = function () 
        this.user.first_name = 'First';
        this.user.last_name = 'Last';
        this.user.email = 'email@address.com';
        this.user.access = 'institution';
        return this.initialized;
    ;
]);

angular.module('myApp').controller('myCtrl', ['$scope', 'userService', function ($scope, userService) 
    $scope.user = userService.user;
    $scope.callUserService = function () 
        userService.isAuthenticated().then(function () 
            $scope.thencalled = true;
        );
    ;
]);

【讨论】:

【参考方案5】:

这是您服务的正确代码:

myApp.service('userService', [
  '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) 

    var user = 
      access: false
    ;

    var me = this;

    this.initialized = false;
    this.isAuthenticated = function() 

      var deferred = $q.defer();
      user = 
        first_name: 'First',
        last_name: 'Last',
        email: 'email@address.com',
        access: 'institution'
      ;
      deferred.resolve(user);
      me.initialized = true;

      return deferred.promise;
    ;
  
]);

那么你的控制器应该相应地对齐:

myApp.run([
  '$rootScope', 'userService', function($rootScope, userService) 
    return userService.isAuthenticated().then(function(user) 
      if (user) 
        // You have access to the object you passed in the service, not to the response.
        // You should either put response.data on the user or use a different property.
        return $rootScope.$broadcast('login', user.email);  
       else 
        return userService.logout();
      
    );
  
]);

关于服务的几点注意事项:

仅在服务中公开需要公开的内容。用户应保留在内部,并且只能由 getter 访问。

在函数中,使用 'me' 服务来避免 JavaScript 的极端情况。

我猜到了 initialized 的意思,如果我猜错了,请随时纠正我。

【讨论】:

【参考方案6】:

来自您的服务方法:

function serviceMethod() 
    return $timeout(function() 
        return 
            property: 'value'
        ;
    , 1000);

在你的控制器中:

serviceName
    .serviceMethod()
    .then(function(data)
        //handle the success condition here
        var x = data.property
    );

【讨论】:

@BenjaminGruenbaum 是的,你是对的,我不知道$timeout 实际上返回了一个承诺,serviceMethod 可以缩短为:return $timeout(function() return property: 'value' ; , 1000); 这可能有效,但肯定不是推荐的返回承诺的方法 @BenjaminGruenbaum 我做了,现在返回 $timeout 生成的承诺。 很好,我收回了我的-1。 啊好吧,但我仍然同意他的观点,即使出于不同的原因!我很欣赏downvote令人沮丧,我们可以使用upvotes来帮助好的内容浮到顶部,但在这种情况下,我觉得你的回答没有帮助,因为它无法解释 $q 的机制,而是提出$q 的抽象。对 Promise 不熟悉的人,或者像我一样熟悉 Promise 但对 Angular 不熟悉的人,可能会完全搞错!【参考方案7】:

试试这个:

myApp.service('userService', [
    '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) 
      var deferred= $q.defer();
      this.user = 
        access: false
      ;
      try
      
      this.isAuthenticated = function() 
        this.user = 
          first_name: 'First',
          last_name: 'Last',
          email: 'email@address.com',
          access: 'institution'
        ;
        deferred.resolve();
      ;
    
    catch
    
        deferred.reject();
    

    return deferred.promise;
  ]);

【讨论】:

有人能告诉我为什么这被标记为否决吗?

使用 AngularJS 立即返回一个已解决的承诺

】使用AngularJS立即返回一个已解决的承诺【英文标题】:ImmediatelyreturnaresolvedpromiseusingAngularJS【发布时间】:2014-09-0718:53:41【问题描述】:我正在努力理解JavaScript(尤其是AngularJS)中的承诺。我在服务中有一个函数,我们称之为... 查看详情

使用 AngularJS 限制从 Grails Restful 服务返回的数据

】使用AngularJS限制从GrailsRestful服务返回的数据【英文标题】:RestrictingDataReturnedfromaGrailsRestfulServicewithAngularJS【发布时间】:2014-05-2419:50:52【问题描述】:我是使用AngularJS的新手,想使用REST与Grails集成。虽然我找到了很多关于使... 查看详情

如何使用 .success 和 .error 在 Angularjs 中扩展 $q 承诺

】如何使用.success和.error在Angularjs中扩展$q承诺【英文标题】:HowcanIextend$qpromiseinAngularjswitha.successand.error【发布时间】:2013-05-2317:29:34【问题描述】:我在AngularJS的自定义服务中编写了这个小代码。为我服务:vardeferred=$q.defer();va... 查看详情

angularjs$q

1、$q$q是Angular的一种内置服务,它可以使你异步地执行函数,并且当函数执行完成时它允许你使用函数的返回值(或异常)。2、deferdefer的字面意思是延迟, $q.defer()  可以创建一个deferred实例(延迟对象实例)。deferre... 查看详情

AngularJS 使用控制器中的函数从服务中返回数据以用于 ng-repeat

】AngularJS使用控制器中的函数从服务中返回数据以用于ng-repeat【英文标题】:AngularJSuseafunctioninacontrollertoreturndatafromaservicetobeusedinng-repeat【发布时间】:2014-01-2310:31:26【问题描述】:我正在尝试使用控制器中的函数来返回数据,... 查看详情

angularjs中的promise

promise是一种用异步方式处理值的方法,promise是对象,代表了一个函数最终可能的返回值或抛出的异常。在与远程对象打交道非常有用,可以把它们看成一个远程对象的代理。要在Angular中创建promise需要使用内置的$q服务。先用fac... 查看详情

从 angularjs 模态对话服务返回数据

】从angularjs模态对话服务返回数据【英文标题】:returningdatafromangularjsmodaldialogservice【发布时间】:2014-01-2820:35:47【问题描述】:我对AngularJS还很陌生,并且在从模态对话服务返回数据时遇到了问题。基本上,我复制了DanWahlin的... 查看详情

angularjs异步处理$q.defer()

看别人的项目中有用到vardef=$q.defer()返回一个deferred异步对象def当代码逻辑遇到def.resolve(rtns);deferred状态为执行成功,返回rtns为从后台取到的数据,可以继续执行def.then(),def.done()deferred.reject(data);执行到这里时,改变deferred状态为... 查看详情

如何使用 AngularJS 和 Restangular 返回/编辑 REST 资源

】如何使用AngularJS和Restangular返回/编辑REST资源【英文标题】:Howtoreturn/editRESTresourcewithAngularJS&Restangular【发布时间】:2013-06-1916:49:38【问题描述】:在AngularJS中使用Restangular,不断从Mongolab获取一个object对象。我确信它与Promise... 查看详情

如何使用 AngularJS 和 Restangular 返回/编辑 REST 资源

】如何使用AngularJS和Restangular返回/编辑REST资源【英文标题】:Howtoreturn/editRESTresourcewithAngularJS&Restangular【发布时间】:2013-06-1916:49:38【问题描述】:在AngularJS中使用Restangular,不断从Mongolab获取一个object对象。我确信它与Promise... 查看详情

如何使用 PostgreSQL 将数据从 AngularJS 前端传递到 Nodejs 后端?

】如何使用PostgreSQL将数据从AngularJS前端传递到Nodejs后端?【英文标题】:HowtopassdatafromAngularJSfrontendtoNodejsbackendusingPostgreSQL?【发布时间】:2016-12-2905:47:11【问题描述】:使用HTML和AngularJS准备好登录页面和注册页面。我已连接数... 查看详情

从 Promise 内部返回已解决的 Observable

...份验证令牌。(将来可能会使用文件系统)。我的问题是如何从我的http服务返回已解决的承诺,以便我可以订阅组件中的 查看详情

如何模拟在 AngularJS Jasmine 单元测试中返回承诺的服务?

】如何模拟在AngularJSJasmine单元测试中返回承诺的服务?【英文标题】:HowdoImockaservicethatreturnspromiseinAngularJSJasmineunittest?【发布时间】:2014-07-0511:36:08【问题描述】:我有myService使用myOtherService,它进行远程调用,返回承诺:angula... 查看详情

AngularJS $http 从失败的 CORS 请求返回状态码 0

】AngularJS$http从失败的CORS请求返回状态码0【英文标题】:AngularJS$httpreturnsstatuscode0fromfailedCORSrequest【发布时间】:2014-10-1919:10:49【问题描述】:好的,我已经找遍了这个。基本上我们使用的是跨域请求的$http请求。我们的服务器... 查看详情

如何使用angularjs从json文件中获取数据

】如何使用angularjs从json文件中获取数据【英文标题】:howtogetdatafromjsonfileusingangularjs【发布时间】:2014-09-0615:39:13【问题描述】:我正在从json文件中获取数据以显示在表格中,但只有第一次我从getdata()获取数据时,下一次出现... 查看详情

如何使用angularjs

   本期更新,博主将给大家分享一些AngularJs常用的一些属性和方法,AngularJS是由Google的员工MiškoHevery从2009年开始着手开发。这是一个非常好的构想,该项目目前已由Google正式支持,有一个全职的开发团队继续开... 查看详情

如何正确地将控制器和服务从 AngularJS 转换为使用 ng-resource

】如何正确地将控制器和服务从AngularJS转换为使用ng-resource【英文标题】:HowtoproperlyconvertcontrollerandservicefromAngularJStousingng-resource【发布时间】:2016-02-2608:26:09【问题描述】:我最近才开始学习ng-resource。我想知道在将我的常规Ang... 查看详情

如何在 AngularJS 中使用 $http.get 从 jsp 页面获取响应?

】如何在AngularJS中使用$http.get从jsp页面获取响应?【英文标题】:Howtogetaresponsefromajsppageusing$http.getinAngularJS?【发布时间】:2018-02-2522:52:50【问题描述】:我是AngularJS中JSON和$http服务的新手。我正在尝试从jsp文件(位于同一文件... 查看详情