开发者问题收集

AngularJs 无法从函数返回数据[重复]

2019-04-02
81

我正在尝试从函数 getShiftDetails() 返回数据

SS_Mod_App.controller("SS_Ctrl", function ($scope, $http, $location, $window, $sce) {

     var ShiftDetails = []; var ShiftDtls = [];

    ShiftDtls = getShiftDetails();
      //  alert(ShiftDtls);  -->  ShiftDtls undefined
        insertDaysHtml(ShiftDtls);  

function getShiftDetails() {
        $http({
            method: 'GET',
            url: 'http://xxxxx/api/Shift/GetShiftDetails',
            params: { }
            , headers: { 'Content-Type': 'application/json; charset=utf-8', 'dataType': 'json' }
        }).then(function successCallback(response) {
            ShiftDetails = response.data;               --> successful response with data     
            alert(JSON.stringify(ShiftDetails.length));    -->  getting length 21 here
            return ShiftDetails;  
        }, function errorCallback(response) {  });
    }

并想将其传递给下一个函数 insertDaysHtml,我想在其中迭代它并获取如下所示的 ShiftDetails 数据,但出现如下所示的错误。

 function insertDaysHtml(ShiftDtls) {    
        alert(JSON.stringify($scope.ShiftDetails.length));   --> Length "0" here
    //alert(JSON.stringify(ShiftDtls.length)); Error msg: TypeError: Cannot read property 'length' of undefined
    // if (ShiftDtls.length > 0) {  --> Error msg: TypeError: Cannot read property 'length' of undefined

        if ($scope.ShiftDtls.length > 0) {  
           // alert(ShiftDtls.length );
            dayhtmlContent = dayhtmlContent + '<tr> '
            for (var j = 0; j <= ShiftDtls.length; j++) {
                dayhtmlContent = dayhtmlContent + '<td> $scope.ShiftDtls[ ' + j + '].ShiftName[0]));'                 
            }

        $scope.divHtmlDay = $sce.trustAsHtml(dayhtmlContent);
    }
3个回答

首先 ,您没有从 getShiftDetails() 函数返回任何内容。因此,您需要添加一个 return 语句,如下所示:

function getShiftDetails() {
  return $http({
    method: 'GET',
    url: 'http://xxxxx/api/Shift/GetShiftDetails',
    params: {},
    headers: {
      'Content-Type': 'application/json; charset=utf-8',
      'dataType': 'json'
    }
  }).then(function successCallback(response) {
    ShiftDetails = response.data;
    -- > successful response with data
    alert(JSON.stringify(ShiftDetails.length));
    -- > getting length 21 here
    return ShiftDetails;
  }, function errorCallback(response) {});
}

其次 ,您的 getShiftDetails() 函数正在使用 Promise 进行异步调用。因此,在获取数据之前会执行以下语句

ShiftDtls = getShiftDetails();
//  alert(ShiftDtls);  -->  ShiftDtls undefined
insertDaysHtml(ShiftDtls); 
//this statement is executing before getting data 

因此,一种可能的解决方案是从已解析的请求函数调用 insertDaysHtml() 函数。如下所示:

function getShiftDetails() {
  $http({
    method: 'GET',
    url: 'http://xxxxx/api/Shift/GetShiftDetails',
    params: {},
    headers: {
      'Content-Type': 'application/json; charset=utf-8',
      'dataType': 'json'
    }
  }).then(function successCallback(response) {
    ShiftDetails = response.data;
    -- > successful response with data
    alert(JSON.stringify(ShiftDetails.length));
    -- > getting length 21 here
    insertDaysHtml(response.data); //invoke function from here
  }, function errorCallback(response) {});
}

希望这会对您有所帮助。谢谢!

Adnan Sharif
2019-04-02

getShiftDetails 使用 Promise 执行异步调用。您可以阅读有关 JavaScript 中 Promise 和 async 的工作原理的说明。但要回答您的问题,

ShiftDtls = getShiftDetails();

如果您看到函数 getShiftDetails 的主体,它不会返回任何内容。因此,您会得到 undefined

要使其正常工作,请在 successCallback 内执行您的操作,而不是返回值。

Jayendra Sharan
2019-04-02

要理解发生了什么,想象一下 HTTP 执行长时间运行,而不是在本地主机上循环,这需要大量时间。 在 javascript 中,这可以通过异步调用实现,因此程序在等待响应时不会被阻止,当响应最终出现时,它会在所谓的回调函数中处理。 要强制控制器等待响应,您必须使用 Promises。

// Service
YearService.getCurrentYearId = function(){
  var defferer = $q.defer();
  $http.get('years')
    .then(function(response){
      deffer = response;
  });
  return defferer.promise;
};
  
 // Controller
function getData(){
  YearService.getYears()
    .then(function(data){
      YearCtrl.years = data;
  });
}

我必须注意的另一件事: 代码中的行:

return ShiftDetails;

这是非常错误的,您试图从函数中的函数返回。 在 javascript 中有很多回调函数,它们不容易保持干净,但您必须更多地了解它们,因为它们确实有帮助。 它们不是由你调用的,所以如果你尝试从它们返回,它们的响应不会被你的变量捕获,你想要从回调函数返回的唯一原因是如果你想在某个点停止执行,例如,如果你使用 forEach 函数,用条件查找数组中的第一个元素,你不想在找到第一个满足条件的元素后检查元素,如下所示:

var first;
elements.forEach(function(element) {
  if(isFirst(element)){
    first = element;
    return;
  }
});
Benjámin Pálfi
2019-04-02