Изменить (при ответе на вопрос Обновить )
Проблема
Способ взаимодействия контроллера (-ов) с вашей фабрикой является хрупким и подвержен ошибкам.См. Ваш код, прокомментированный ниже:
// factory
app.factory('companies', ['$http', function($http) {
data = [];
for (let i = 1; i < 11; i++) {
// you CANNOT control when this is going to return
$http.get('https://examplepage.com/wp-json/wp/v2/categories?per_page=50&page=' + i)
.then(function(response) {
// so this doesn't push to `data` synchronously, this DOES NOT
// guarantee you when you return data, every response.data will be there
data.push(response.data);
console.log('data', data);
},
function(err) {
return err;
});
}
// this will always be returned empty ([], as you initialized it) because
// the async responses (commented above) haven't arrived when this lint his hit.
return data;
}]);
// controller
$scope.companies = companies; // so, companies will always be [] (empty array)
Решение
Вы должны сильно рассмотреть возможность изменения способа реализации фабрики на что-то вроде этого:
Идея :
- Не вызывать конечную точку
x
(11) раз для получения 550 предметов (50 * 11 раз) - Предоставить функцию (
getCompanies
) на фабрике, которая принимает параметры itemsPerPage
и page
, таким образом вы можете получить столько элементов, сколько захотите и на нужной странице.То есть: для получения 550 наименований вы должны позвонить по этому номеру: companies.getCompanies(550);
- С любого контроллера, который хочет получить компании, звоните
companies.getCompanies
Код :
// factory
app.factory('companies', ['$http', function($http) {
function fnGetCompanies(itemsPerPage, page) {
var ipp = itemsPerPage || 50; // 50 default
var page = page || 0; // 0 default page
// return the promise instead of data directly since you cannot return the value directly from an asynchronous call
return $http
.get('https://examplepage.com/wp-json/wp/v2/categories?per_page=' + ipp + '&page=' + page)
.then(
function(response) {
// and then return the data once the promise is resolved
return response.data;
},
function(err) {
return err;
}
);
}
// provide a `getCompanies` function from this factory
return {
getCompanies: fnGetCompanies
}
}]);
// controller
// get 550 items starting from 0
companies.getCompanies(550, 0).then(function(companies) {
$scope.companies = companies;
});
Дополнительные примечания
Помните Невозможно вернуться из асинхронного вызова внутри синхронного метода
Исходное сообщение
Вы можете сначала использовать Array.prototype.reduce , чтобы преобразовать структуру из нескольких массивов в один массив, подобный следующему:
$scope.companies = companies.reduce(function(prevArr, currentArr) { return prevArr.concat(currentArr);}, []);
Это преобразует структуру следующим образом:
[
[{id: 1, name: 'A'}, {id: 2, name: 'B'}, {id: 3, name: 'C'}],
[{id: 4, name: 'D'}, {id: 5, name: 'E'}, {id: 6, name: 'F'}]
];
в это:
[{"id": 1,"name": "A"},{"id": 2,"name": "B"},{ "id": 3,"name": "C"},{"id": 4,"name": "D"},{"id": 5,"name": "E"},{"id": 6,"name": "F"}]
Простая демонстрация:
var companies =[
[{id: 1, name: 'A'}, {id: 2, name: 'B'}, {id: 3, name: 'C'}],
[{id: 4, name: 'D'}, {id: 5, name: 'E'}, {id: 6, name: 'F'}]
];
console.log(companies.reduce(function(prev, current) { return prev.concat(current);}, []));