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

Angularjs : variable which is returned by a function in controller is "undefined"

本文关键字:未定义 未定义的 变量 函数 控制器 Angularjs 返回      更新时间:2023-12-22
<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 ,但我不能只返回它。

我将不胜感激任何建议。

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);
    });
};

复习异步编程和承诺可能会有所帮助

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

当你的工作$http你的使用承诺。

因此,它是异步的。我不太确定这是否是您要做的,但最好提及您不能返回值并期望立即使用它。我的意思是这行不通:

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

您需要做的是返回一个承诺,然后注册并说"当承诺解析时运行我的代码"。在这种情况下,一旦$http请求返回,承诺将解决。当$http为你回报一个承诺时,你所要做的就是回报它。

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

所以在你的代码中,只需在$http之前返回.

您需要从$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,因此您不能从中"返回值"并在代码中使用它,除非该代码位于.then()或成功或失败处理程序.catch()并且这些处理程序直到以后才会运行

你应该使用 $q 返回 promise

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;
    };

在这里,您的getEmailAddress函数不返回任何内容。您必须至少返回$http(返回一个承诺(并将结果作为承诺进行处理。或者你可以更好地在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

(simple plunkr(

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

索引.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。 $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;
}]);