Как вызвать функцию ПОСЛЕ выполнения промисов?

rocket27

Пишу свой первый проект на AngularJS. Приложение мониторит песочницу инстаграма по двум введеным хештегам, для каждого хаштега выводятся изображения сожержащие данный тег в соответствующие поля в представлении. Также есть результирующее поле для вывода результатов по совпадающим тегам, то есть если изображение сожержит оба введенных тега, то оно попадает также и в поле результата.

Есть функция, которая перебирает оба массива, в которые кладутся результаты http запроса по каждому из хештегов, ищет совпадение по id, кладет совпадающие элементы во временный массив, который потом чистится от дублирующих элементов и окончательный результат кладется в результирующий массив, из которого происходит вывод изображений в представление в поле результата.

У меня не получается сделать вызов этой функции ПОСЛЕ того как отработают оба http запроса и массивы заполнятся объектами из ответа, чтобы функции было с чем работать. Что бы я ни делал, вызов функции происходит раньше выполнения асинхронных запросов. Пробовал делать как здесь, использовал как Promise.all() так и ангуляровский $q, все равно вызов функции отбора результатов происходит раньше чем приходит ответ от api.

Фактори выполняющая запрос к api:

angular.module('requestToApi', []) .constant('clientID', 'myClientID') .factory('getResponseApi', function(clientID, $http) { return { request: function (tag) { return $http({ method: 'GET', url: 'https://api.instagram.com/v1/tags/' + tag + '/media/recent', params: {access_token: clientID} }) } } });

Контроллер:

angular.module("app").controller("appCtrl", ['$scope', 'getResponseApi', '$q', '$interval', function($scope, getResponseApi, $q, $interval, $stateProvider) { $scope.dataStorage1 = []; $scope.dataStorage2 = []; $scope.commonDataStorage = []; $scope.tag1 = "nature"; $scope.tag2 = "mountains"; $scope.getDataLeft = function() { getResponseApi.request($scope.tag1).then(function(response) { $scope.dataStorage1 = response.data.data; }); }; $scope.getDataRight = function() { getResponseApi.request($scope.tag2).then(function(response) { $scope.dataStorage2 = response.data.data; }); }; $scope.appStart = function() { $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function() { getCommonData(); }) }; $scope.appStart(); function getCommonData() { let commonArray = [], val1, val2; for(val1 of $scope.dataStorage1) { for (val2 of $scope.dataStorage2) { if (val1.caption.id === val2.caption.id) { commonArray.unshift(val1); $scope.commonDataStorage = (commonArray.filter((item) => itemCheck(item))); } } } } function itemCheck(item) { let temp = []; if (temp.indexOf(item.caption.id) === -1) { temp.unshift(item.caption.id); return true } return false; } }]);

По идее вся магия должна происходить здесь,

$scope.appStart = function() { $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function() { getCommonData(); })
};

но магия не происходит. Подскажите что делаю не так?

Так же хотелось бы вынести функцию getCommonData в отдельный factory, можно ли это сделать если она использует $scope?

1 ответ

rocket27

$http возвращает промис в angular, в getResponseApi вы используете его правильно, а getData* не возвращает ничего.

Вариант перевозврата промиса от getResponseApi

$scope.getDataLeft = function () { return getResponseApi.request($scope.tag1);
};
$scope.getDataRight = function () { return getResponseApi.request($scope.tag2);
};
$scope.appStart = function () { $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function (response1, response2) { $scope.dataStorage1 = response1.data.data; $scope.dataStorage2 = response2.data.data; getCommonData(); })
};

И вариант с новым промисом в getData*:

$scope.getDataLeft = function () { return $q(function(resolve, reject) { getResponseApi.request($scope.tag1).then(function (response) { $scope.dataStorage1 = response.data.data; resolve(); }); });
};
$scope.appStart = function () { $q.all([$scope.getDataLeft(), $scope.getDataRight()]).then(function () { getCommonData(); })
};

licensed under cc by-sa 3.0 with attribution.