Angularjs:由控制器中的函数返回的变量是“未定义的”

时间:2016-04-05 08:27:30

标签: javascript angularjs

<script type="text/javascript">
angular.module('angularApp', ['dialogs.main'])
.controller('TableController', function(dialogs, $http){

    function getEmailAddress(){
        var emailAddress ="empty";
        $http({
            //The http method is defined here, which works as expected
        }).then(function succes(response) {
            emailAddress = response.data;
            console.log(emailAddress + " : getEmailAddress success");//From this log, I can see what I expected
            return emailAddress; //However, this doesn't return the value, which can be seen in the log.
            // return {
            //  emailAddress:emailAddress
            // };  //This way doesn't work either
        }, function resendError() {
            return "Error!";
        });
    };

    this.resendConfirmationMail = function(orderId){
        //Inside this function, the function above is going to be used.
    };
});
</script>

我要做的是创建/使用一个返回值的函数,该函数来自http函数。

如上所述,有两个函数,其中一个应该返回一个名为emailAddress的变量,但返回的变量被描述为undefined,甚至不是empty ,作为其初始值。

我可以从console.log看到正确的返回值,但我不能只返回它。

我很感激任何建议。

6 个答案:

答案 0 :(得分:1)

getEmailAddress是一个异步函数(因为它使用$http也是异步的)。您可以使用getEmailAddress方法返回承诺,并使用then获取电子邮件地址:

function getEmailAddress() {
    return $http({
        //The http method is defined here, which works as expected
    });
}

this.resendConfirmationMail = function (orderId) {
    getEmailAddress().then(function (emailAddress) {
        console.log(emailAddress);
    });
};

了解异步编程和Promises

可能会有所帮助

Here是一个很好的答案,总结了使用异步函数。

答案 1 :(得分:1)

当您使用$http使用承诺时。

就像它的异步。我不太确定这是否是您尝试做的事情,但我觉得最好提及您无法返回价值并期望立即消费。我的意思是这不会起作用:

function test () {
    $http.get('url')
        .then(x => x.data);
}

var data = test();

您需要做的是与您一起回复承诺,然后注册以在承诺解决时运行我的代码&#39;。在这种情况下,一旦$http请求返回,promise将解决。当$http为你返回一个承诺时,你所要做的就是返回它。

function test () {
    return $http.get('url')
        .then(x => x.data);
}

test().then(data => {
    //use data
});

因此,在您的代码中,只需在$http之前返回。

答案 2 :(得分:1)

您需要从$http调用中返回承诺,然后在需要时使用.then()来检索它。

angular.module('angularApp', ['dialogs.main'])
.controller('TableController', function(dialogs, $http){

    function getEmailAddress(){
        var emailAddress ="empty";
        return $http({
            //The http method is defined here, which works as expected
        }).then(function succes(response) {
            emailAddress = response.data;
            return emailAddress;
        }, function resendError() {
            return "Error!";
        });
    };

    this.resendConfirmationMail = function(orderId){
        //Inside this function, the function above is going to be used.
        getEmailaAddress().then(function(emailAddress) {
            // use the email address here.
        });
    };
});

这里要记住的重要事项是$http异步运行,因此您无法返回值&#39;从它开始并在代码中使用它,除非该代码在.then().catch()成功或失败处理程序中,并且这些处理程序将在以后运行

答案 3 :(得分:0)

您应该使用$ q

返回承诺
function getEmailAddress(){
        var deferred = $q.defer();
        var emailAddress ="empty";
        $http({
            //The http method is defined here, which works as expected
        }).then(function (response) {
            emailAddress = response.data;
            console.log(emailAddress + " : getEmailAddress success");//From this log, I can see what I expected
             deferred.resolve(emailAddress)
        }, function () {
            deferred.reject(""Error!")
        });
       return deferred.promise;
    };

答案 4 :(得分:0)

此处 getEmailAddress 函数不返回任何内容。 你必须至少返回$ http(返回一个promise)来处理结果作为一个promise。 或者您可以在getEmailAddress中更好地创建promise实例并直接在resendConfirmationMail中处理它

 function getEmailAddress(){
   var deferred = $q.defer();
   var emailAddress ="empty";
   $http({
     //The http method is defined here, which works as expected
   }).then(function succes(response) {
     emailAddress = response.data;
     deferred.resolve(emailAddress)
   }, function resendError() {
     deferred.reject("Error");
   });
   // This is what you return
   return deferred.promise;
};

this.resendConfirmationMail = function(orderId){
  getEmailAddress()
    .then(function(emailResponse){
      // Do the things
    }, function(errorMessage){
      // Error handler
    }
  );
};

有用的文档页面:https://docs.angularjs.org/api/ng/service/ $ q

答案 5 :(得分:0)

simple plunkr

事实上,$ http会返回一个承诺。此外,一个好的模式是首先处理服务中返回的承诺以执行任何与数据相关的操作,然后将该承诺从“链”传递到可以处理UI操作的控制器。我已经包含了一个简化的plunkr,它显示了这些承诺如何从服务传递到控制器。只需点击控制器中的“获取数据”按钮,您就会看到事件如何与一系列'alert()s'一起工作。注意,我使用$ timeout作为$ http的替代品。承诺处理将使用$ http相同。更多详情如下:

  

index.html:开始一切。获取数据按钮调用getData()   控制器中的方法。

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
    <script src="app.js"></script>
    <script src="mock_ajax_service.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Click on button to request data and handle the promise chain</p>

    <div>
      <button ng-click="getData()">Get Data!</button>
    </div>
  </body>

</html>
  

app.js:getData()反过来调用'mock ajax'中的requestData()方法   服务。它等待从服务返回的承诺   返回处理UI事务,即显示警报。

var app = angular.module('plunker', ['mockjaxservice_module']);

app.controller('MainCtrl', ['$scope', 'mockajaxservice', 
  function($scope, mockajaxservice) {
  $scope.name = 'World';

        var requestDataSuccess = function (results) {

      console.log('handle success data in controller/UI');
      alert('handle success data in controller/UI');
          return;
        }

        var requestDataFail = function (results) {

          console.log('handle failed data in controller/UI');
          return;
        }     

  $scope.getData = function () {

    var UIPromise = mockajaxservice.requestData();

    UIPromise.then(requestDataSuccess,requestDataFail);
  }
}]);
  

mock_ajax_service.js:这里,服务模拟了一个模拟ajax调用   使用$ timeout,由控制器按钮调用。 $超时,   很像$ http,返回一个真正的承诺。一旦承诺   返回,处理(警报),并将承诺传递给   链到控制器(返回;)

'use strict';

var mockAjaxModule = angular.module('mockjaxservice_module', []);

mockAjaxModule.factory('mockajaxservice', ['$timeout', function ($timeout) {

    this.service_count = 0;

    this.service_count_object = {

        count:0
    }

    var that = this; 

    var requestDataSuccess = function (results) {
        console.log('handle success data in service');  
        alert('handle success data in service then pass it up to controller');
        that.service_count = 10;
        that.service_count_object.count = 10;
        that.utcTime = Math.floor((new Date()).getTime() / 1000);
      return that;
    }

    var requestDataFail = function (results) {

      console.log('handle failed data in service')
      return that;
    }       

    this.requestData = function () {

        var requestDataPromise = $timeout(function() {

        }, 500);

        requestDataPromise.then(requestDataSuccess,requestDataFail);

        return requestDataPromise;

    }

    return this;

}]);