Я пытаюсь вернуть данные из функции 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);
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


getShiftDetails выполняет асинхронный вызов, используя Promise. Вы можете прочитать о том, как работает Promise и асинхронность в JavaScript, для разъяснения. Но чтобы ответить на ваш вопрос,
ShiftDtls = getShiftDetails();
Если вы видите тело функции getShiftDetails, она ничего не возвращает. Итак, вы получаете undefined.
Чтобы заставить это работать, делайте свое дело внутри successCallback вместо того, чтобы возвращать значение.
Прежде всего, вы ничего не возвращаете из функции 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) {});
}
Надеюсь, что это поможет вам. Спасибо!
@user11130182 user11130182 вы вызываете функцию insertDaysHtml() из других частей вашего кода? Вы удалили insertDaysHtml(ShiftDtls); из своего кода перед его тестированием?
Чтобы понять, что происходит, представьте, что HTTP выполняет длительный цикл вместо того, чтобы делать круг на вашем локальном хосте, это занимает много времени. В javascript это стало возможным благодаря асинхронному вызову, поэтому программа не блокируется в ожидании ответа, а когда ответ наконец получен, он обрабатывается в так называемой функции обратного вызова. Чтобы заставить контроллер ждать ответа, вы должны использовать промисы.
// 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 очень много callback-функций, их непросто содержать в чистоте, но вам придется узнать о них больше, потому что они действительно помогают. Они не вызываются вами, поэтому, если вы попытаетесь вернуться из них, их ответ не будет пойман вашими переменными, хотя единственная причина, по которой вы хотите вернуться из функции обратного вызова, - это если вы хотите остановить выполнение в точке , например, если вы используете функцию forEach для поиска первого элемента в массиве с условием, вы не хотите проверять элементы после того, как вы нашли первый элемент, удовлетворяющий условию, примерно так:
var first;
elements.forEach(function(element) {
if (isFirst(element)){
first = element;
return;
}
});
Я думаю, вы просите меня вызвать метод insertDaysHtml(response.data); внутри getShiftDetails после успешного обратного вызова. Даже после этого я получаю Невозможно прочитать свойство «длина» неопределенного значения для (var j = 0; j <= ShiftDtls.length; j++) {.